2009年12月26日 星期六

Ubuntu中如何安裝gcc及kernel原始程式

在Ubuntu中安裝任何東西時,可使用apt-get這個好用的程式。例如,要安裝gcc時,只要執行下面指令,就可以安裝完成

sudo apt-get build-dep gcc

若要安裝kernel source,則使用下列指令

sudo apt-get install linux-source

若要安裝kernel source中的一些header檔案,則使用下列指令

sudo apt-get install linux-headers

指令會回傳不同release的list,此時使用uname –r 指令先確定目前的linux release 後,再重新執行

sudo apt-get install linux-headers-2.6.31-14-generic

2009年12月15日 星期二

DB2 Process Model

從接到應用程式的請求開始,DB2就由一連串的agent(又稱EDU, Engine Dispatchable Units)協同作業,完成使用者的請求。9.5版以前,除了Windows是使用Thread model外,Unix和Linux都是使用Process model來建立這些agent,較耗費系統資源。9.5版以後,所有的agent統一使用Thread model。

如下圖所示,依據使用的Protocol不同,每一個Instance都會有一個相對應的Listener來等候使用者的請求,Listener有下列三種

  • db2ipccm:處理來自Local Client的請求,當client與server位於同一個OS image,可以使用IPC的 protocol與此Listener溝通
  • db2tcpcm:處理遠端Client的請求,當client 與server位於不同OS image時,使用TCP/IP與此Listener溝通
  • db2tcpdm:處理DB2的 Discovery工具所發出的請求,DB2有個Discovery工具可以找尋遠端的Instance中,有那些資料庫可以使用。這類的請求由此Listener處理

image

Listener接受到請求後,會指定一個coordinator agent(db2agent)給該應用程式連線,被assign的db2agent就在DB2中,擔任應用程式的代理人,負責與應用程式溝通,處理應用程式的請求。若在一個Partitioned的資料庫環境,或INTRA_PARALLEL參數設為Yes時,coordinator agent會再把工作交代給 subagent來處理,coordinator agent的角色就變成協調這些subagent完成工作。

如果Access Plan Manager分析結果產生的 Access Plan表示需要進行Prefetch,coordinator agent會送 prefetch的請求到 Prefetch Queue。每個資料庫都有一個Prefetcher,prefetcher從Queue中取得請求後,會把資料由Disk讀取到Bufferpool中。一但資料存在Bufferpool後,coordinator就可以依據應用程式的需求更新資料,更新的資料會暫存在bufferpool中,直到page cleaner將其再寫回Disk。

除此之外,每個應用程式所發出的交易都會由 logger這個agent寫入 transaction log,以備recovery之需。

下圖展示每個agent作用的範圍

image

接下來介紹db2相關的process。如前所述,9.5版以後 agent是採用thread model,所有的agent都成為依附在主 process下的一個thread,如此一來可大幅減少

Process名稱 描述 適用平台
db2acd 為autonomic computing的 daemon,用來處理client端與automatic相關的工作,如healther monitor、automatic maintenance utilities等。health-monitor process以一個DB2 fenced mode的process執行,在Windows環境,以db2fmp的方式呈現 只限Linux及Unix
db2ckpwd 在DB2 Server端檢驗使用者的ID/Password 只限Linux及Unix
db2fmcd 預設的fault monitor coordinator daemon,每一個實體的機器會有一個 只限Unix
db2fmd 預設的monitor daemon,每個DB2的instance都有一個fault monitor。這個daemon會受 db2fmcd所監控,若把這個process殺掉,db2fmcd會再把這個process叫起來 只限Unix
db2fmp 在DB2的firewall外,在DB2 server上執行user的code。每個db2fmp基本上都是獨立的process,不過對於某些種類的 runtime,可以用multithread的方式執行 所有LUW平台
db2sysc DB2 System Controller引擎。在DB2 9.5中,每個partition中只會有一個db2sysc引擎 process,所有的EDU(Engine Dispathcable Unit)都會以一個Thread的形式,掛在這個process下。一但這個process停止了,DB2 server就無法作用了。 (p.s. 在Windows平台中,這個process名稱為 db2syscs) 所有LUW平台
db2vend Fenced vendor process,這是在DB2 9.5版後才引進。在Threaded的引擎下,DB2無法讓vendor的code更改它的signal mask、啟動新的thread或破壞agent的stack。所以所有的vendor code都是獨立於DB2 engine外,在這個process執行 只限Linux及Unix
db2wdog DB2 watchdog. 這個process是db2sysc的 parent process,負責下列internal事項
  - 當db2sysc不正常結束時,清除IPC資源
  - 產生 db2fmp及 health-monitor process。當這些process不正常結束時,清除該db2fmp佔用的系統資源,若需要重啟health monitor,也會進行重啟動作
只限Linux及Unix

2009年12月12日 星期六

清除 Linux memory的 cache

有很多種方法可以查看Linux 記憶體的使用狀況,如vmstat、free、nmon等,這裡以 free 指令為例

[root@db01 ~]# free
                                 total           used                  free     shared    buffers     cached
Mem:                       5144296    3008448    2135848          0       8600        2819464
-/+ buffers/cache:       180384    4963912
Swap:      6160376      18484    6141892

這裡buffers是放即將被寫入硬碟資料的緩衝區;而cache則是資料預先自硬碟讀取暫存在記憶體的暫存區。Linux 作業系統傾向會把資料cache在記憶體中,即使應用程式結束,也不會立即將cache的資料清除。

以下介紹如何把cache的資料清除:

Writing to this will cause the kernel to drop clean caches, dentries and inodes from memory, causing that memory to become free.

To free pagecache:

  • echo 1 > /proc/sys/vm/drop_caches

To free dentries and inodes:

  • echo 2 > /proc/sys/vm/drop_caches

To free pagecache, dentries and inodes:

  • echo 3 > /proc/sys/vm/drop_caches

As this is a non-destructive operation, and dirty objects are not freeable, the user should run "sync" first in order to make sure all cached objects are freed.

Linux Memory使用資訊

轉貼自 http://ssorc.tw/rewrite.php/read-599.html

free

                      total         used           free     shared     buffers      cached
Mem:       1023916     975816       48100              0      26376     465844
-/+ buffers/cache:      483596      540320
Swap:      2096440    105564    1990876

計算方式

                      total         used           free     shared     buffers      cached
Mem:                a               b                c              d           e               f
-/+ buffers/cache:             g                h
Swap:               i                j                 k

a = 總記憶體大小
b = 配給 buffers 與 cache 的記憶體大小(包含未用的 buffers 與 cache)
c = 剩下的記憶體大小
e = 配給 buffers 但未用的記憶體大小
f = 配給 cache 但未用的記憶體大小
g = buffers 與 cache 被使用掉的記憶體大小,也就是實際被應用程式用走的
h = 那這個就是實際剩下的記憶體大小
a  = b + c
a  = g + h
g = b  - e  -  f
h = c  + e  + f

由上面的計算可以知道 MEM:Free 欄位是真的沒有在使用的記憶體(已減掉Buffer及Cache);MEM:Used欄位的值包含其它程式在使用的記憶體 + Buffer及Cache;-/+buffers/cache:used:是真實其它程式在使用的記憶體(即Mem:used – Mem:buffers – Mem:cached)


buffer 與 cache 的區別:
A buffer is something that has yet to be "written" to disk.
A cache is something that has been "read" from the disk and stored for later use.
Quote: http://www.ubuntu.org.tw/modules/newbb/viewtopic.php?topic_id=6132

一般情況下,Linux kernel 會盡可能多地利用 RAM 的空閑空間作為 cache/buffer 以最大幅度地提高系統性能。當系統中運行的應用程序占用的 RAM 增加時,則將 cache/buffer 所占用的空間釋放出來,讓渡給應用程序使用。

Quote: http://web.mit.edu/rhel-doc/4/RH-DOCS/rhel-isa-zh_tw-4/s1-resource-rhlspec.html

Mem: 那一行顯示了實際記憶體的使用率;
Swap: 顯示的是系統 swap 空間的使用率;
-/+ buffers/cache: 則是目前撥給系統緩衝區的實體記憶體數量。

Quote: http://wiki.gentoo.tw/mediawiki/index.php/FAQ_LINUXMEMORY

記憶體管理的概觀
當系統開機一段時間後,像是「top」這種傳統的 Unix 工具常常回報少的可憐的可用記憶體數值,在我寫這篇文章的系統中,就算我總共有 512 MB 的記憶體在我的系統裡,但約開機m後三個小時,我只剩下 60 MB 的可用記憶體,那些記憶體到底跑到那裡去了?

用掉最多記憶體的地方是磁碟快取 (disk cache),目前它總共用了超過 290 MB 的記憶 (在 top 裡的「cached」項目中),快取記憶體 (cached memory) 基本上是空閒的,當有新/執行中的程式需要記憶體的話,它會快速的被取回來。

為什麼 Linux 使用這麼多的記憶體來當作磁碟快取 (disk cache) 呢?主要的原因便是:假如 RAM 沒有被使用的話,它便是閒放在那邊浪費著不用。如果把資料放在用 RAM 組成的磁碟上,它的存取速度比直接從硬碟上存取還要快上 1000 倍。假如在快取裡找不到該資料,當然還是得直接從磁碟裡存取,但就如同上面說的,您將可以節省些微的存取時間。

Quote: http://7cc.tw/bencandy.php?fid=18&id=3280

Free中的buffer和cache︰(它們都是佔用內存)︰

buffer : 作為buffer cache的內存,是塊設備的讀寫緩沖區

cache: 作為page cache的內存, 文件系統的cache

如果 cache 的值很大,說明cache住的文件數很多。如果頻繁訪問到的文件都能被cache住,那麼磁盤的讀IO bi會非常小。

/proc/meminfo 解釋參考: http://www.redhat.com/advice/tips/meminfo.html
ref: http://www.wujianrong.com/archives/linux/2.html
ref: http://linux.chinaunix.net/bbs/viewthread.php?tid=887896
對 Memory Usage 的詳細說明及當 Out of Memory 的解決方法參考: http://rimuhosting.com/howto/memory.jsp
Out of Memory
      more /var/log/messages

kernel: Mem-info:
kernel: Zone:DMA freepages:  2916 min:     0 low:     0 high:     0
kernel: Zone:Normal freepages:   758 min:   766 low:  4031 high:  5791
kernel: Zone:HighMem freepages:   125 min:   253 low:   506 high:   759
kernel: Free pages:        3799 (   125 HighMem)
kernel: ( Active: 237940/1195, inactive_laundry: 1, inactive_clean: 0, free: 3799 )
kernel:   aa:0 ac:0 id:0 il:0 ic:0 fr:2916
kernel:   aa:209592 ac:2087 id:1190 il:1 ic:0 fr:758
kernel:   aa:26033 ac:232 id:0 il:0 ic:0 fr:125
kernel: 0*4kB 2*8kB 4*16kB 2*32kB 4*64kB 2*128kB 1*256kB 1*512kB 0*1024kB 1*2048kB 2*4096kB = 11664kB)
kernel: 8*4kB 1*8kB 175*16kB 6*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 3032kB)
kernel: 1*4kB 0*8kB 1*16kB 1*32kB 1*64kB 1*128kB 1*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 500kB)
kernel: Swap cache: add 5156731, delete 5156620, find 19439534/21006374, race 0+19
kernel: 4115 pages of slabcache
kernel: 1566 pages of kernel stacks
kernel: 13 lowmem pagetables, 5378 highmem pagetables
kernel: 32 bounce buffer pages, 32 are on the emergency list
kernel: Free swap:            0kB
kernel: 261760 pages of RAM
kernel: 32384 pages of HIGHMEM
kernel: 5781 reserved pages
kernel: 14591 pages shared
kernel: 116 pages swap cached
kernel: Out of Memory: Killed process 25580 (java).

Quote: http://rimuhosting.com/howto/memory.jsp Resolving: High Java Memory Usage

To determine how much memory you can spare for Java, try this: stop your Java process; run free -m; subtract the 'used' value from the "-/+ cache" row from the total memory allocated to your server and then subtract another 'just in case' margin of about 10% of your total server memory.  The number you come up with is a rough indicator of the largest -Xmx setting you can use on your server.

意思就是配給 -Xmx數值多少m = a - g - a x 10%,應該是這樣子吧!!!@@

DB2 Database Performance Tuning實例

目前進行一個應用系統的效能測試,所測試的交易含有大量的資料庫Select/Insert/Update的動作,執行完一次交易大概要執行大約3、4千行的 Dynamic SQL語句。測試結果發現效能非常地差,同時50個使用者執行該交易,就需要32分鐘才能將交易做完,利用nmon來監控其CPU使用率發現這30多分鐘的CPU都是滿載使用。

image

因為這樣的效能實在不能接受,因此開始進行DB2及應用程式的效能調整,因為是第一次有機會做這樣的測試,所以一切就在邊作邊學的過程進行,幸好DB2 Infocenter寫的都還滿詳細的,讓我能一步步達到我的目的。接下來就分享整個Tunning的過程。

首先,要找出使應用程式DB使用效能的原因,我們必需啟用DB2的 monitor switch收及一些統計資訊,輸入 DB2 GET MONITOR SWITCHES 指令可以得到目前這些switche的狀態。

[db2inst1@db01 source_db]$ db2 get monitor switches

            Monitor Recording Switches

Switch list for db partition number 0
Buffer Pool Activity Information  (BUFFERPOOL) = OFF
Lock Information                        (LOCK) = OFF
Sorting Information                     (SORT) = OFF
SQL Statement Information          (STATEMENT) = OFF
Table Activity Information             (TABLE) = OFF
Take Timestamp Information         (TIMESTAMP) = ON  12/12/2009 15:13:18.256534
Unit of Work Information                 (UOW) = OFF

如上面所示,目前除了TIMESTAMP這個預設會打開的switch外,其它都是關閉的狀態,要啟動任一個 switch只需輸入 db2 UPDATE MONITOR SWITCHES USING XXX ON,比方說若要啟用LOCK這個switch的話,就輸入db2 UPDATE MONITOR SWITCHES USING LOCK ON,結果如下

[db2inst1@db01 source_db]$ db2 update monitor switches using lock on
DB20000I  The UPDATE MONITOR SWITCHES command completed successfully.

回到DB2的效能檢視,因為DB2的使用率已達到100%,因此暫不朝向有太多lock的方向思考,且db2 v9版以後,已經有很多Database Configuration參數,如heap size、bufferpool等都可以動態調整了,也不朝向Database Configuration的方向思考。排除上述的因子後,決定直接看 SQL執行的效能如何。

要查看SQL執行效能,首先要把 STATEMENT 這個 Monitor Switch打開,如下

[db2inst1@db01 source_db]$ db2 update monitor switches using statement on
DB20000I  The UPDATE MONITOR SWITCHES command completed successfully.

接著模擬1個使用者,執行所要測試的交易,交易執行完後,使用 GET SNAPSHOT FOR DYNAMIC SQL ON    database_name  的指令,收集執行一次交易,所有會執行的dynamic SQL統計資訊。將其導向一個檔案

[db2inst1@db01 source_db]$ db2 get snapshot for dynamic sql on test_db > executed_sql

檢視該檔案,可發現每一筆錄到的dynamic SQL的Snapshot的格式如下,在這裡會用到的是 Total Execution Time、Total CPU Time及 SQL statement這三個欄位的資訊(用藍色標出的部分)

Number of executions               = 1
Number of compilations             = 1
Worst preparation time (ms)        = 7
Best preparation time (ms)         = 7
Internal rows deleted              = 0
Internal rows inserted             = 0
Rows read                          = 1590
Internal rows updated              = 0
Rows written                       = 0
Statement sorts                    = 0
Statement sort overflows           = 0
Total sort time                    = 0
Buffer pool data logical reads     = Not Collected
Buffer pool data physical reads    = Not Collected
Buffer pool temporary data logical reads   = Not Collected
Buffer pool temporary data physical reads  = Not Collected
Buffer pool index logical reads    = Not Collected
Buffer pool index physical reads   = Not Collected
Buffer pool temporary index logical reads  = Not Collected
Buffer pool temporary index physical reads = Not Collected
Buffer pool xda logical reads      = Not Collected
Buffer pool xda physical reads     = Not Collected
Buffer pool temporary xda logical reads    = Not Collected
Buffer pool temporary xda physical reads   = Not Collected
Total execution time (sec.microsec)= 25.435582
Total user cpu time (sec.microsec) = 25.377444
Total system cpu time (sec.microsec)= 0.000000
Total statistic fabrication time (milliseconds) = 0
Total synchronous runstats time  (milliseconds) = 0
 
Statement text                     = SELECT CURR_NO,   DEPT_NO,        GL_ACCT_NO,     SUM(CASH_DR_NO_OF_VOH) CSHDRVOH,        SUM(TRANSFER_DR_NO_OF_VOH) TRNDRVOH,    SUM(CASH_CR_NO_OF_VOH) CSHCRVOH,        SUM(TRANSFER_CR_NO_OF_VOH) TRNCRVOH   FROM ACCT01  T1  WHERE VOH_SEQ_NO = (SELECT MIN(VOH_SEQ_NO) FROM ACCT01                   WHERE T1.VOH_NO = VOH_NO                        AND T1.BRANCH_NO = BRANCH_NO)   AND VOH_DATE = '20090518'       AND VOH_DATE = ORG_VOH_DATE     AND (VOH_SPLIT_NO = '00' OR VOH_SPLIT_NO = '99')        AND BRANCH_NO = '9964' GROUP BY CURR_NO, DEPT_NO, GL_ACCT_NO

因為所錄到的SQL數量非常龐大,無法用肉眼找出那些SQL耗掉最多的CPU time,因此在這裡寫了一個簡單的小程式來過濾這些record。程式內容如下(下列程式會挑出所有執行時間大於0.5秒的SQL,若要改成其它時間,只需在藍色該行的if 敘述中改為其它值

#!/usr/bin/perl
undef $/;
my $data = <>;
my $long_execution_sql_count=0;
while($data=~/(Total execution time \(sec.microsec\)= (.+?)\n.+?\n.+?\n.+?\n.+?\n.+?\n)/g)
{
        if ($2>0.5)          #這裡使用0.5會挑出所有執行時間大於0.5秒的SQL。
        {
                print $1,"\n";
                $long_execution_sql_count++;
        }
}

print "Total Long Execution SQLs: ",$long_execution_sql_count;

使用此小程式來過濾Dynamic SQL snapshot 所錄到的結果,可發現這個應用程式最耗時的SQL語句如下:

 Total execution time (sec.microsec)= 27.081611 
Total user cpu time (sec.microsec) = 27.067162
 
Total system cpu time (sec.microsec)= 0.000000
Total statistic fabrication time (milliseconds) = 0
Total synchronous runstats time  (milliseconds) = 0
Statement text                     = SELECT CURR_NO, DEPT_NO, GL_ACCT_NO, SUM(CASH_DR_NO_OF_VOH)CSHDRVOH,
          SUM(TRANSFER_DR_NO_OF_VOH)TRNDRVOH, SUM(CASH_CR_NO_OF_VOH)
          CSHCRVOH, SUM(TRANSFER_CR_NO_OF_VOH)TRNCRVOH
  FROM ACCT01 T1
  WHERE VOH_SEQ_NO =
     (SELECT MIN(VOH_SEQ_NO)
     FROM ACCT01
     WHERE T1.VOH_NO =VOH_NO AND T1.BRANCH_NO =BRANCH_NO)AND VOH_DATE
          ='20090518' AND ORG_VOH_DATE= '20090518' AND (VOH_SPLIT_NO = '00' OR VOH_SPLIT_NO = '99')
          AND BRANCH_NO ='9964'
  GROUP BY CURR_NO, DEPT_NO, GL_ACCT_NO

是的,只單單執行一次這個SQL就要花費 27秒,很顯然地,它就是要被tune的SQL。接下來使用db2expln這個命令來Explain DB2的Optimizer倒底是如何來執行這個SQL的,下面範例會把explain的結果,輸出到 sql_explain這個檔案中。先把上述要explain的SQL語句,寫入input_sql這個檔案中,執行下列指令

[db2inst1@db01 ~]$ db2expln -database test_db -stmtfile input_sql -terminator ';' -o sql_explain -graph

DB2 Universal Database Version 9.5, 5622-044 (c) Copyright IBM Corp. 1991, 2007
Licensed Material - Program Property of IBM
IBM DB2 Universal Database SQL and XQUERY Explain Tool

Output is available in "sql_explain".

接下來檢視sql_explain這個output檔案,以下擷取 Optimizer Plan這個Tree的結果,可以看到這個SQL已經使用Index Search了,所以應該也不是沒建 index的問題。

Rows  
                   Operator
                     (ID)  
                     Cost  
                   1.03085
                   RETURN 
                    ( 1)  
                   4517.06
                     |    
                   1.03085
                    GRPBY 
                    ( 2)  
                   4517.06
                     |    
                   1.03085
                   TBSCAN 
                    ( 3)  
                   4517.06
                     |    
                   1.03085
                    SORT  
                    ( 4)  
                   4517.06
                     |    
                   3.43618
                   NLJOIN 
                    ( 5)  
                   4517.06
                  /       \
          6.87235            0.5  
           FETCH           FILTER 
           ( 6)             ( 8)  
          556.13           3547.89
         /       \           |    
  171.809    5.10504e+06      1   
  IXSCAN     Table:         GRPBY 
   ( 7)      DB2INST1       ( 9)  
  93.3323    ACCT01        3547.89
    |                        |    
5.10504e+06               0.531085
Index:                     IXSCAN 
DB2ADMIN                    (10)  
ACCT01                    3547.89 
                            |      
                        5.10504e+06
                        Index:     
                        DB2ADMIN   
                        ACCT01
     

由上面的Tree可以看到,最大的cost來自Index Scan,判斷可能是因為資料太多而導致,再仔細檢視一下這個耗時的SQL,發現它是由一個主要的Select join Sub-Select的結果組成,且主Select與Sub-Select都是指向同一個Table。看到標示紅色部分的SQL的寫法有點奇怪T1.VOH_NO其實就是VOH_NO;而T1.BRANCH_NO其實就是BRANCH_NO,因為ACCT01這個表格有很多record,如果有500萬筆的record的話,這樣寫就等於做500萬筆對500萬筆資料的比對,難怪會消耗大量的CPU time。

SELECT CURR_NO, DEPT_NO, GL_ACCT_NO, SUM(CASH_DR_NO_OF_VOH)CSHDRVOH,
          SUM(TRANSFER_DR_NO_OF_VOH)TRNDRVOH, SUM(CASH_CR_NO_OF_VOH)
          CSHCRVOH, SUM(TRANSFER_CR_NO_OF_VOH)TRNCRVOH
  FROM ACCT01 T1
  WHERE VOH_SEQ_NO =
     (SELECT MIN(VOH_SEQ_NO)
     FROM ACCT01
     WHERE T1.VOH_NO =VOH_NO AND T1.BRANCH_NO =BRANCH_NO
)AND VOH_DATE
          ='20090518' AND ORG_VOH_DATE= '20090518' AND (VOH_SPLIT_NO = '00' OR VOH_SPLIT_NO = '99')
          AND BRANCH_NO ='9964'
  GROUP BY CURR_NO, DEPT_NO, GL_ACCT_NO

經過與程式開發人員確認後,原本的Sub-select還是有其意義,因此需保留。幸好,他想到在該Sub-select中加入另一個條件,縮小資料的範圍,上述的Sub-select修改如下

SELECT MIN(VOH_SEQ_NO) FROM ACCT01
            WHERE T1.VOH_NO = VOH_NO AND VOH_DATE = '20090518'
             AND T1.BRANCH_NO = BRANCH_NO

結果重新執行這個SQL,就發現CPU time大幅縮小

Total execution time (sec.microsec)= 0.051433
Total user cpu time (sec.microsec) = 0.037532

Total system cpu time (sec.microsec)= 0.000000
Total statistic fabrication time (milliseconds) = 0
Total synchronous runstats time  (milliseconds) = 0
Statement text                     = SELECT CURR_NO, DEPT_NO, GL_ACCT_NO, SUM(CASH_DR_NO_OF_VOH)CSHDRVOH,
          SUM(TRANSFER_DR_NO_OF_VOH)TRNDRVOH, SUM(CASH_CR_NO_OF_VOH)
          CSHCRVOH, SUM(TRANSFER_CR_NO_OF_VOH)TRNCRVOH
  FROM ACCT01 T1
  WHERE VOH_SEQ_NO =
     (SELECT MIN(VOH_SEQ_NO) FROM ACCT01
            WHERE T1.VOH_NO = VOH_NO AND VOH_DATE = '20090518'
             AND T1.BRANCH_NO = BRANCH_NO)AND VOH_DATE
          ='20090518' AND ORG_VOH_DATE= '20090518' AND (VOH_SPLIT_NO = '00' OR VOH_SPLIT_NO = '99')
          AND BRANCH_NO ='9964'
  GROUP BY CURR_NO, DEPT_NO, GL_ACCT_NO

接著再回到50個人來測試這個交易,發現執行時間有所縮減,由原本的32分鐘,縮減至27分鐘,這樣的縮減還是無法令人滿意…

再做一次 Dynamic SQL statement 的 Snapshot,發現大多數的SQL statement的執行時間都在3秒以內,只是CPU time 只要0.07秒!  這應該是執行時間很久的原因吧!

Total execution time (sec.microsec)= 2.891382
Total user cpu time (sec.microsec) = 0.076323

Total system cpu time (sec.microsec)= 0.000000
Total statistic fabrication time (milliseconds) = 0
Total synchronous runstats time  (milliseconds) = 0
Statement text                     = UPDATE ACCT04   SET CASH_DR_AMT = 0, TRANSFER_DR_AMT = 0, CASH_CR_AMT = 0,        TRANSFER_CR_AMT = 0, CASH_DR_NO_OF_VOH = 0,     TRANSFER_DR_NO_OF_VOH = 0, CASH_CR_NO_OF_VOH = 0,       TRANSFER_CR_NO_OF_VOH = 0,      DR_ACCT_CODE_CURR_BAL = DR_ACCT_CODE_PREV_BAL,          CR_ACCT_CODE_CURR_BAL = CR_ACCT_CODE_PREV_BAL  WHERE TX_DATE =  '20090518'      AND BRANCH_NO = '9963'

檢視一下ACCT04這個表格,它足足佔用了5G的空間,而且這個交易執行非常多次這個SQL,如果時間都等在從這個表格找資料、更新資料,會大幅拖慢交易執行速度。為了避免這個問題,這裡考慮把這個表格放在獨立的 TABLE SPACE中,然後assign給他獨立的Buffer Pool。

以下為建立這個獨立的Buffer Pool的指令
CREATE BUFFERPOOL ACCT04 IMMEDIATE  SIZE 100000 PAGESIZE 4 K ;
再來是建立這個獨立的Table Space的指令,選用上面建立的獨立Buffer Pool
CREATE  LARGE  TABLESPACE ACCT04_TABSPACE PAGESIZE 4 K  MANAGED BY AUTOMATIC STORAGE EXTENTSIZE 64 OVERHEAD 10.5 PREFETCHSIZE 64 TRANSFERRATE 0.14 BUFFERPOOL  ACCT04 ;
最後再把ACCT04這個表格建在新建的 TABLE SPACE上,再執行50人的case時,就發現時間可由原本的 32分鐘縮減到13分鐘,且DB2的 CPU utilization也不會在100%使用率持續太久(如下圖),Tuning暫告完成

image

2009年12月9日 星期三

DB2 List Applications -- 列出目前連結到資料庫的所有應用程式

List application命令可以列出目前連結到資料庫的所有應用程式資訊,若下命令時沒有指定要看那個資料庫,則所有的資料庫連結都會被列出

image

以下為使用 DB2 LIST APPLICATIONS FOR SAMPLE SHOW DETAIL指令後,所得到的資訊

DB2INST1 db2jcc_application 3638 9.181.158.212.38221.09120917185 03285 1 0 273 UOW Waiting 12/10/2009 07:47:53.099138 xxxDB /mnt/db_data/db2inst1/NODE0000/SQL00001/

以下簡介每個欄位所代表意義

DB2INST1: Connection Authentication ID
db2jcc_application : Application Name
3957: Application Handle
9.181.158.212.38221.09120917185 : Application ID
03285: Sequence Number
1: Number of agent
0: Database partition number
273: Coordinator PID
UOW Waiting:Status
12/10/2009 07:47:53.099138:Status change time
xxxDB: DB Name
/mnt/db_data/db2inst1/NODE0000/SQL00001/ : DB Path

DB2 Update Monitor Switches

無論是要使用 event monitor 或是 snapshot monitor,若要監控相關資訊,需要打開相關的monitor switches,使用 get monitor switches可以得到目前 monitor的狀態。

[db2inst1@db01 ~]$ db2 get monitor switches

            Monitor Recording Switches

Switch list for db partition number 0
Buffer Pool Activity Information  (BUFFERPOOL) = OFF
Lock Information                        (LOCK) = OFF
Sorting Information                     (SORT) = OFF
SQL Statement Information          (STATEMENT) = OFF
Table Activity Information             (TABLE) = OFF
Take Timestamp Information         (TIMESTAMP) = ON  12/08/2009 10:20:24.309342
Unit of Work Information                 (UOW) = OFF

若要把某個monitor switch設為 on,使用 update monitor switches for xxx on 的指令,如下列指令可以將 bufferpool這個 switch打開

[db2inst1@db01 ~]$ db2 update monitor switches using bufferpool on

要注意的是,所做的monitor switch更動只限於此次 attach到instance的 session有效,一但離線後再連回去,monitor switch就會被重設為預設值了

重設Monitor Switches值

Monitor switch所收集的值從打開後,會一直累積,若要Reset其數值,可使用 RESET MONITOR 指令,用法如下

image