名稱
pgbench -- 在PostgreSQL中執行基準線測試
大綱pgbench -i [option...] [dbname]
pgbench [option...] [dbname]
描述pgbench是一個用於在PostgreSQL資料庫中執行基準測試的簡單程式。pgbench在多個併發的資料庫會話中反覆執行一系列相同的SQL命令,並計算事務執行的平均速率(每秒執行的事務個數)。 pgbench預設測試的是一種基於TPC-B的鬆散的測試,即一個事務中包括5個SELECT,UPDATE和INSERT語句。同時允許基於開發者自己書寫的事務指令碼檔案進行其他場景的測試。
典型的pgbench輸出如下:
transactiontype: TPC-B (sort of)scaling factor: 10query mode: simplenumber of clients: 10number of threads: 1number of transactions per client: 1000number of transactions actually processed: 10000/10000tps = 85.184871 (including connections establishing)tps = 85.296346 (excluding connections establishing)
前六行顯示了一些非常重要的引數。接下來顯示的是已經完成的事務和預計應該執行的事務個數。這兩個數值應該是相等的,如果不相等說明存在執行失敗的情況(如果指定為-T模式,則只打印實際完成的事務數量)。最後兩行顯示的是每秒完成的事務數量(包含連線建立時間和不包含連線建立時間分別計算出的平均值)。
預設的TPC-B-like事務測試需要預先設定特定的表。pgbench呼叫-i(初始化)選項來建立和填充這些表。在使用一個定製化指令碼測試時,不需要呼叫-i選項初始化,但是需要對這個定製化指令碼需要的表進行初始化。初始化過程類似如下:
pgbench -i [ other-options ] dbname
dbname用於指定一個可以用來測試的資料庫的資料庫名稱。你可能需要指定-h,-p,-U等引數來連線資料庫伺服器。
注意
pgbench -i命令會建立四個表(pgbench_accounts, pgbench_branches, pgbench_history, 和pgbench_tellers),建立這幾個表會執行對應表的刪除動作。執行前應確認對應資料庫中是否已經有這些表,是否會誤刪除。
按照預設的比例因子1,這些表按如下行數初始化:
表名 行數---------------------------------pgbench_branches 1pgbench_tellers 10pgbench_accounts 100000pgbench_history 0
可以透過指定-s(比例因子)引數來增加初始化時各表的行數。-F(填充因子)引數此時也可以同時使用。
做了必要的設定後,就可以使用如下命令進行基準測試(不需要再使用-i引數)
pgbench [ options ] dbname
在幾乎所有情況下,您將需要一些選項做出有用的測試。最重要的選項是-c(客戶端數量),-t(事務數量),-T(時間限制)和-f(定製指令碼)
具體引數見下文的完整列表。
選項下面的選項分成三個不同類別,分別是使用在資料庫初始化階段,基準測試執行階段或兩個階段都可以使用。
初始化選項pgbench接受以下命令列引數:
-i
--initialize
呼叫初始化模式.
-F fillfactor
--fillfactor=fillfactor
使用給出的填充因子建立pgbench_accounts,pgbench_tellers,pgbench_branches等表.預設值是100.
-n
--no-vacuum
初始化後不執行vacuum。
-q
--quiet
日誌模式切換為靜默方式。即每五秒只打印一條進度資訊,預設是每10萬條記錄列印一條日誌,這樣通常會有很多日誌產生。
-s scale_factor
--scale=scale_factor
生成的行數乘以比例因子。比如,-s 100會在pgbench_accounts表中將會生成1000萬條記錄。預設值是1。當指定的引數超過20000時,為了能夠容納賬戶識別符號的範圍,儲存這些資訊的列欄位型別會調整為大整形。
--foreign-keys
在預設建立的表上建立外來鍵。
--index-tablespace=index_tablespace
在指定的表空間上建立索引。
--tablespace=tablespace
在指定的表空間上建立預設表。
--unlogged-tables
Create all tables as unlogged tables, rather thanpermanent tables.(建立臨時表?)
基準測試選項pgbench接受以下命令列基準測試引數引數:
-c clients
--client=clients
模擬的客戶數量,具體指併發執行的資料庫會話數。預設值為1。
-C
--connect
每個事務都新建立一個連線來執行,而不是僅使用一個客戶端連線。這個對於測試連線過載是有意義的。
-d
--debug
列印除錯資訊
-D varname=value
--define=varname=value
定義一個客戶定製指令碼適用的變數。允許多個-D選項。
-f filename
--file=filename
從指定檔案中讀取事務指令碼。具體參見下面的詳細介紹。-N, -S和-f是互斥的。
-j threads
--jobs=threads
指定工作執行緒數量。在多核場景下使用多於一個執行緒是有意義的。由於每個執行緒會被分配相同數量的客戶端數目,所以客戶端數量必須設定為執行緒數目的整數倍。該引數預設值為1。
-l
--log
記錄每個執行緒的耗時到日誌檔案中。詳細內容見下文。
-M querymode
--protocol=querymode
用於向伺服器提交查詢的協議:
simple: 使用簡單協議.extended: 使用擴充套件協議.prepared: 使用擴充套件協議with prepared statements.預設值為簡單協議. (詳細說明參考Chapter 49 。)
-n
--no-vacuum
測試執行前不執行vacuum。如果執行的是一個不包含預設表( pgbench_accounts, pgbench_branches, pgbench_history和pgbench_tellers.
)的定製測試時,這個選項是必要的。
-N
--skip-some-updates
不更新表pgbench_tellers和pgbench_branches.設定後會避免更新這兩個表。但是這樣返會使該測試與TPC-B測試產生差異。
-P sec
--progress=sec
每秒顯示一次進度報告。報告包括已執行時間,上次報告到當前的tps、事務延遲時間、標準誤差。節流(-R)模式下,誤差是從事務計劃開始時間計算,而不是實際的事務開始時間,因此,這個時間還包含了平均執行計劃延遲時間。
-r
--report-latencies
基準測試執行完成後報告每個命令的平均延遲時間(從客戶角度看到的執行時間)。詳細內容見下文。
-R rate
--rate=rate
按執行速率執行事務,而不是儘可能快地執行(預設方式)。這個速率指定的是每秒的事務數。如果指定的速率比最大可能速率還大,則這個速率引數不會對結果產生影響。
速率以沿著Poisson-distributed計劃時間線開始的事務為目標。期待的開始時間基於客戶第一次啟動時間向前,而不是最後一個事務的完成時間。這種方法意味著當事務經過了原先的計劃結束時間,後續的事務仍然有可能趕上
The rate is targeted by starting transactions along aPoisson-distributed schedule time line. The expected start time schedule movesforward based on when the client first started, not when the previoustransaction ended. That approach means that when transactions go past theiroriginal scheduled end time, it is possible for later ones to catch up again.
當節流開關是有效的,則執行結束時報告的事務時延是從計劃開始時間計算的,因此這個時間是包含了每個事務等待前一個事務完成的這段時間的。等待時間又稱為計劃延遲時間,並且它的平均時間和最大時間也會被分別輸出。因此基於實際事務開始時間的事務時延,也就是,在資料庫中執行事務實際花費的時間,可以用減去時延報告中的計劃延遲時間來計算。
一個高的計劃延遲時間表明系統無法以指定的速率、客戶端數量和執行緒數來處理事務。當平均事務執行時間比事務執行間隔時間要長時,每個連續的事務將會下跌,測試的時間越長,計劃延遲時間將會持續越長。當這些事情發生時,你需要降低定製的事務速率。
-s scale_factor
--scale=scale_factor
在pgbench報告中輸出定製的比例因子。內建測試不需要設定這個引數。透過計算在pgbench_branches表中的行數,正確的比例因子將會被檢測到。但是,如果透過-f執行客戶定製的基準測試,比例因子會被報告為1,除非使用了這個引數。
-S
--select-only
執行select-only事務測試而不是TPC-B-like測試。
-t transactions
--transactions=transactions
每個客戶端執行的事務數量,預設值為10.
-T seconds
--time=seconds
執行測試這麼多秒,而不是每個客戶端執行固定數量的事務。-t - t是互相排斥的。
-v
--vacuum-all
執行測試前先對四張基準表做vacuum。如果不指定-n也不執行-v,預設對錶pgbench_tellers和pgbench_branches做vacuum並將pgbench_history表truncate掉。
--aggregate-interval=seconds
彙總時間間隔長度。只有-l和這個引數同時使用才有效。日誌包含每個間隔的概要(事務數量,最大最小時延和兩個額外的用於方差估計的欄位)
--sampling-rate=rate
抽樣速率,將資料寫入日誌時使用,用於降低生產的日誌數量。如果設定了這個引數,只有指定的事務部分才會被記錄。1.0表示所有事務都被記錄。0.05表示只有5%的事務會被記錄。當處理日誌檔案時記得考慮取樣率。例如,當計算tps值,你需要乘上對應的數量(比如0.01取樣率,你實際只是獲得了1/100的實際tps)。
通用引數pgbench接受以下命令列常見引數:
-h hostname
--host=hostname
資料庫伺服器主機名稱
-p port
--port=port
資料庫伺服器埠號
-U login
--username=login
用來登陸的資料庫使用者名稱稱
-V
--version
列印pgbench版本
-?
--help
顯示pgbench命令幫助資訊
說明在pgbench中執行的所謂的“事務”是什麼?預設的事務指令碼在每個事務中執行如下七條語句:
BEGIN;UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;SELECT abalance FROM pgbench_accounts WHERE aid = :aid;UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);END;如果你指定了-N,第4步和第5步不會執行。如果指定了-S,則只有select語句會執行。
客戶化定製指令碼透過使用-f引數讀取檔案替換掉預設的事務指令碼,pgbench可以實現客戶化基準測試場景。在這種情況下,一個“事務”指的是一個SQL指令碼檔案。你甚至可以指定多個SQL指令碼(多個-f引數),在這種情況下,每次客戶端會話會隨機選擇一個指令碼開始一個新事務。
指令碼檔案格式是每一條SQL命令獨佔一行。一行多個SQL命令是不支援的。空行和以--開頭的行會被忽略。指令碼中還可以錄入由pgbench解釋的"元命令",具體描述見下文:
pgbench有一個簡單的指令碼檔案的變數替換功能。變數可以使用上面提到的-D引數設定,也可以使用pgbench元命令設定(下面會詳細介紹)。除了透過-D引數設定的變數,還有一些變數是預設設定的,列舉在了表G-1中。-D設定的變數優先於預設變數。一旦設定後,一個變數的值就可以透過:變數名稱的方式插入到一個SQL命令中。當超過一個會話執行時,每個會話都可以有自己的一組變數。
表G-1.自動變數
變數名稱
描述
scale
當前的比例因子
client_id
客戶端會話唯一的數字識別(從0開始)
指令碼檔案元命令以(\)開始。元命令引數由空格分隔。支援如下元命令:
\set varname operand1 [ operator operand2 ]
設定變數varname整數值計算公式。每個運算元可以是一個整數常量或是用:variablename引用的一個是整數型別的變數。運算子可以是+、-、*、/。
例:
\set ntellers 10 * :scale
\setrandom varname min max
設定變數varname為一個在min和max之間的隨機整數。min和max可以是一個整數常量或是用:variablename引用的一個是整數型別的變數。
例:
\setrandom aid 1 :naccounts
\sleep number [ us | ms | s ]
指定指令碼休眠時間,單位可以是微妙(us),毫秒(ms)或秒(s)。時間單位預設是秒。number可以是一個整數常量或用:variablename引用的一個是整數型別的變數。
例:
\sleep 10 ms
\setshell varname command [ argument ... ]
設定變數varname為shell命令command的返回值,這個命令的標準輸出必須是一個整數。argument可以是一個文字常量或者是用 :variablename表示的一個任意型別的變數。如果想要使用以:開頭的argument,需要在argument 的開頭增加一個額外的:。
例e:
\setshell variable_to_be_assigned command literal_argument:variable ::literal_starting_with_colon
\shell command [ argument ... ]
和 \setshell相同,但是結果會被忽略。
例:
\shell command literal_argument :variable::literal_starting_with_colon
作為一個例子,內建的TPC-B-like事務的完整定義如下:
\setnbranches :scale\set ntellers 10 * :scale\set naccounts 100000 * :scale\setrandom aid 1 :naccounts\setrandom bid 1 :nbranches\setrandom tid 1 :ntellers\setrandom delta -5000 5000BEGIN;UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid =:aid;SELECT abalance FROM pgbench_accounts WHERE aid = :aid;UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid =:tid;UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid =:bid;INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid,:aid, :delta, CURRENT_TIMESTAMP);END;
這個指令碼允許事務的每次迭代引用不同的、隨機選擇的行。(這個例子也說明了為什麼為每個客戶端會話擁有自己的獨立變數是重要的,因為如果不這樣設定他們可能不會使用不同的行,進而造成鎖等待)。
事務處理日誌使用-l引數但沒有使用--aggregate-interval,pgbench會將每個事務消耗的時間寫入到一個日誌檔案中。這個日誌檔案會被命名為pgbench.nnn,nnn是pgbench程序的PID,如果透過-j指定的引數大於等於2,每個pgbench程序會有多個工作執行緒。每個工作執行緒都會有單獨的日誌檔案。第一個工作執行緒的日誌檔名稱與程序的日誌檔名稱相同,其他的日誌檔案會被命名為pgbench_log.nnn.mmm,mmm是一個從1開始的序號。
log的格式如下:
client_id transaction_notime file_notime_epoch time_us[schedule_lag]
time 是事務消耗的全部時間,單位是ms。
file_no用於說明使用的是哪個指令碼檔案(在使用-f指定了多個指令碼檔案時是有用的)。
time_epoch/time_us是用於展示事務完成的UNIX時間戳和一個毫秒偏移量(適用於建立一個ISO 8601與分數秒時間戳)。
schedule_lag是事務計劃開始時間和事務實際開始時間的時間差。這個值只有在使用--rate引數時才會有。
樣例輸出:
0 199 2241 0 1175850568 995598 0 200 2465 0 1175850568998079 0 201 2513 0 1175850569 608 0 202 2038 0 1175850569 2663
當長時間執行測試時,會執行大量的事務,此時日誌檔案會變得很大。--sampling-rate引數可以被用來指定只記錄一定比例的隨機事務樣本執行情況。
聚合的日誌指定--aggregate-interval引數,日誌使用稍微不同的格式:
interval_start num_of_transactionslatency_sum latency_2_sum min_latencymax_latency [lag_sum lag_2_sum min_lag max_lag]
interval_start 是間隔開始時間(UNIX時間戳)
num_of_transactions 是這段時間間隔中執行的事務個數。
latency_sum 是時延總和(可以透過這個值計算平均時延)
接下來的兩個欄位用於方差估計。latency_sum是時延總和,latency_2_sum是 a sum of 2nd powers of latencies。
最後兩個欄位是min_latency (這段時間中的最小時延值)、max_latency(這段時間中的最大時延值)。
在時間間隔中提交的事務才會被統計。最後四個欄位lag_sum,lag_2_sum, min_lag, and max_lag只有在使用了--rate時才會顯示。這幾個時間值是從每個事務等待前一個完成時開始計算,也就是每個事務計劃開始時間和實際開始時間之間的差異。
樣例輸出:
13458285015601 1542744 483552416 61 25731345828503 7884 1979812 565806736 60 14791345828505 7208 1979422 567277552 59 13911345828507 7685 1980268 569784714 60 13981345828509 7073 1979779 573489941 236 1411
注意:非聚合日誌包含了每個客戶化定製指令碼檔案的統計,但是聚合日誌不包含。對於聚合日誌,如果需要每個指令碼資料,要自己聚合整理。
每個語句延遲使用-r引數,pgbench會收集每個客戶端的每條sql語句的執行時間。基準測試完成後,依賴於每個語句的時延,會輸出這些統計項的平均值。
對於預設的事務指令碼,輸出類似如下:
startingvacuum...end.transaction type: TPC-B (sort of)scaling factor: 1query mode: simplenumber of clients: 10number of threads: 1number of transactions per client: 1000number of transactions actually processed: 10000/10000tps = 618.764555 (including connections establishing)tps = 622.977698 (excluding connections establishing)statement latencies in milliseconds: 0.004386 \set nbranches 1 * :scale 0.001343 \set ntellers 10 * :scale 0.001212 \set naccounts 100000 *:scale 0.001310 \setrandom aid 1 :naccounts 0.001073 \setrandom bid 1 :nbranches 0.001005 \setrandom tid 1 :ntellers 0.001078 \setrandom delta -5000 5000 0.326152 BEGIN; 0.603376 UPDATE pgbench_accounts SET abalance =abalance + :delta WHERE aid = :aid; 0.454643 SELECT abalance FROM pgbench_accountsWHERE aid = :aid; 5.528491 UPDATE pgbench_tellers SET tbalance =tbalance + :delta WHERE tid = :tid; 7.335435 UPDATE pgbench_branches SET bbalance =bbalance + :delta WHERE bid = :bid; 0.371851 INSERT INTO pgbench_history (tid, bid,aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta,CURRENT_TIMESTAMP); 1.212976 END;
如果指定了多個事務指令碼檔案,會安裝事務指令碼分別輸出上述統計項的平均值。
注意收集這些額外的時間資訊,每個語句都會增加一些額外開銷。這些會降低平均執行速率和命令的TPS。對速率和TPS的影響隨平臺和硬體的不同而不同。分別統計包含和不包含時延的報告是用來評估這些額外開銷影響是否嚴重的好方法。
最佳實踐很容易使用pgbench生成完全無意義的數字。下面是一些指導方針來幫助你得到有用的結果。
首先,不要相信任何只執行幾秒鐘的測試得出的數字。使用-t和-T選項,使執行至少持續幾分鐘已用於遮蔽掉一些波動。在某些情況下,你可能需要執行幾個小時測試,用於確認測試數字是可再生的(即準確的)。多嘗試幾次測試是個好主意,用於保證測試資料是可再生的。
對於預設的TPC-B-like測試場景,初始化的比例因子(-s)大小至少要和你設定的客戶端數量(-c)相等,否則會有大量時間消耗在更新爭用上。pgbench_branches表中只有-s行,並且每個事務都會嘗試更新這樣行中一行,因此-c值超過-s值將導致大量事務等待其他事務完成。
預設的測試場景也很敏感,這是由於從表初始化開始表中累積的dead記錄和dead空間導致的。要理解對應的結果你必須跟蹤更新總數和什麼時候會啟動vacuum。如果啟用了autovacuum就會導致不可預知的測量效能變化。
pgbench的一個限制是當試圖測試大量的客戶端會話時,pgbench本身會成為瓶頸。這可以透過在非資料庫伺服器的機器上執行pgbench來保證,同時要保證pgbench執行的機器和資料庫伺服器之間是低網路延遲的。同樣,同時在不同機器上(非資料庫伺服器)執行多個pgbench例項也是有效的。