Bulk insert:批量向表中添加數據
bulk insert語法
INSERT INTO sbtest17 VALUES(1,1),(2,2),(3,3)........
實現原理
- --threads:在線程中並發執行多行的插入
- 每個線程都將insert的個數插入到自己的表中
- 每次執行的每個表的insert個數是不均等的,比如--thread=10,--events=1000,預期是10張表中,每張表數據有100行,但實際結果可能是sbtest1中有80行數據,sbtest2中有120行數據....
- --time與--events控制每個線程的執行
- --time:表示在每個配置下測試多少秒
- --events:表示總共寫入多少行數據
- 【重要記錄】比如要測試1000行數據,通過並發的方式來測試bulk insert的性能,將1000行的數據寫入到A表中。
- 預期的實現原理是:將1000行數據,用10個並發,每次並發寫入100行數據,只要一次就將1000行數據寫入到A表中,並且來計算整體的性能寫入結果
- 實際的實現原理是:通過--threads=10,由此創建了10張表,一次將1000行數據不均等的寫入到10張表中,然后在計算出寫入的性能測試結果
復雜概念解讀
- stddev:標准偏差。標准差能反映一個數據集的離散程度,標准偏差越小,這些值偏離平均值就越少,反之亦然。詳解見鏈接 https://baike.baidu.com/item/%E6%A0%87%E5%87%86%E5%81%8F%E5%B7%AE/10963562
注意事項
- --report-interval=2:間隔2秒打印日志,注意:若批量插入的數據比較少,則不會打印出來日志,直接將會打印最終的測試結果
- --time=3:測試的時間一定要注意,若是時間給定的太短,可能會導致數據庫中寫入的數據量與預期的數據量不一致,所以前期一定要做好驗證和檢查。
- 示例:向sbtest1中寫入100000行數據
- 設置--time=3,在3秒內跑結束了run的測試,進入數據庫,查看sbtest1的數據量寫入了多少行,通過select count(*) from sbtest1去查看數據量,實際等於87999,主要是因為--time的值給的太少了,導致數據沒有寫完。
- 重新設置--time=10,再次執行run的測試,完成后進入數據庫查看,100000行數據全部寫入成功
- 示例:向sbtest1中寫入100000行數據
測試場景
測試場景一
按照不同的行數,不考慮並發,對表進行bulk insert測試,觀察在固定的時間內,性能的表現情況
測試場景二
按照不同的行數,根據並發量的要求,對每個表行數進行測試,觀察在不同並發下的性能體現,出現性能的峰值拐點
測試策略
- 手動創建數據庫,示例命名為z_syw_sysbench
- 使用sysbench的生成數據,向數據庫z_syw_sysbench的庫中創建表,
- 根據不同的測試維度,向每個表中插入測試場景表中給定的行數(如10萬行),--thread=100000
- 每個配置下測試1200秒
- 每10秒進行一次采樣
- 分別按照測試步驟執行3次,最后的測試結果取平均值(注:測試3次具有可信度,測試1次的數據很難有說服力)
- 每次的測試結果分別手動記錄,后期做數據分析
測試腳本
#生成數據 sysbench /usr/share/sysbench/bulk_insert.lua --threads=60 --mysql-host=192.168.30.118 --mysql-port=3001 --mysql-db=syw_sysbench --mysql-user=kepler --mysql-password=afdd0b4ad2ec172c586e2150770fbf9e prepare #運行 sysbench /usr/share/sysbench/bulk_insert.lua --threads=1000 --events=100000 --report-interval=10 --time=1200 --mysql-host=192.168.30.118 --mysql-port=3001 --mysql-db=syw_sysbench --mysql-user=kepler --mysql-password=afdd0b4ad2ec172c586e2150770fbf9e run #刪除數據 sysbench /usr/share/sysbench/bulk_insert.lua --threads=1000 --events=100000 --report-interval=10 --time=1200 --mysql-host=192.168.30.118 --mysql-port=3001 --mysql-db=syw_sysbench --mysql-user=kepler --mysql-password=afdd0b4ad2ec172c586e2150770fbf9e cleanup
再次強調的注意事項:bulk insert在使用測試的腳本參數上與insert有所不同,另外,bulk insert在創建表時是空表,不支持在創建表時就寫入數據。詳解如下
- --threads=5:表示要創建5張表,表名稱命名規則為:sbtest1,sbtest2....sbtest5,如果你想創建更過的表,直接修改--threads的值即可
創建的表結構
執行生成數據的腳本后,將會自動在數據庫中創建表
Create Table `sbtest1` ( `id` int NOT NULL, `k` int NOT NULL DEFAULT '0', primary key (id) ) DISTRIBUTE BY HASH(`id`) INDEX_ALL='Y'
測試方法
- 手動創建一個數據庫
- 執行生成數據的SQL
- 進入數據庫,查看表是否按照預期的數量進行創建
- 示例:--threads=1,則創建sbtest1
- 示例:--threads=2,則創建sbtest1、sbtest2,共2張表
- 執行run的SQL
- 進入數據庫,查看表中的數據是否寫入成功
- 通過select count(*) from sbtest1去查看數據是否存在
- 查看注意查看數據量是否與預期的寫入數據量一致
- 示例:--threads=1,--events=100。則sbtest1的表中應該有100行數據
- 示例:--threads=5,--events=100,則有sbtest1、sbtest2、sbtest3、sbtest4、sbtest5,每個表中有20條數據,注意當events太大,則可能會導致數據在表中的分布不均,因此需要每次寫入數據后,通過如下【示例腳本1】的腳本去查看數據量
- 查看測試結果,關注每個結果中給定的參數,詳細的測試結果解讀,見如下的說明
- 將測試結果通過excel記錄,每個測試結果中給定的參數都要詳細的記錄到excel中,方便后期做分析,或與研發人員一起討論數據背后的結論
【示例腳本1】
select (select count(*) from sbtest1) as sbtest1, (select count(*) from sbtest2) as sbtest2, (select count(*) from sbtest3) as sbtest3, (select count(*) from sbtest4) as sbtest4, (select count(*) from sbtest5) as sbtest5,
測試結果記錄表格示例
表格說明:
- 總共的數據量是100 0000行數據的測試結果記錄
- 表格頂部的1、2、3表示測試次數
- events(avg/stddev):
- 【avg】表示平均向表中寫的事務數,注意:這是說的是平均,並不代表每個表中寫的數據量是一樣的,比如:sbtest1的表行數是1200,sbtest2的表行數是300,這2個的平均值是(1200+300)/2=750,因此events(avg/stddev)給定顯示的值是750
- 【stddev】表示:寫入數據庫中的數據的標准偏差(標准偏差的計算公司,去百度搜索)
- execution time(avg/stddev):
- 【avg】:表示執行的平均時間
- 【stddev】:表示:執行測試時間的標准偏差(說明:根據如下的表格中的數據可以看出,當10萬上數據寫入一張表時,是沒有時間偏差的,當10萬行數據寫入到>1張表時,就可能會產生標准偏差,解釋為10萬行數據寫入到5張表中,假如每張表寫入2萬行,但5張表所寫完2萬行數據的時間不一致,因此就有了標准偏差)
- write/total/queries:經過我的觀察,此結果值與給定的--threads的值是相等的,但是目前出現了不一致的情況,后期需要再次觀察一下
- threads fairness后面表格的截圖:是select count(*) from sbtestx的數據統計結果,為了后期來觀察數據寫入的情況(可不用關注)
測試結果分析
root@op06:~# sysbench /usr/share/sysbench/bulk_insert.lua --threads=1 --events=1000000 --report-interval=2 --time=1200 --mysql-host=192.168.30.118 --mysql-port=3001 --mysql-db=syw_sysbench --mysql-user=kepler --mysql-password=afdd0b4ad2ec172c586e2150770fbf9e run sysbench 1.0.18 (using system LuaJIT 2.1.0-beta3) Running the test with following options: Number of threads: 1 Report intermediate results every 2 second(s) Initializing random number generator from current time Initializing worker threads... Threads started! -----report-interval=2每間隔2秒打印的測試結果 true db_bulk_insert_init() failed [ 2s ] thds: 1 tps: 170381.83 qps: 4.49 (r/w/o: 0.00/4.49/0.00) lat (ms,95%): 0.00 err/s: 0.00 reconn/s: 0.00 [ 4s ] thds: 1 tps: 147548.78 qps: 4.50 (r/w/o: 0.00/4.50/0.00) lat (ms,95%): 0.00 err/s: 0.00 reconn/s: 0.00 [ 6s ] thds: 1 tps: 163722.82 qps: 5.00 (r/w/o: 0.00/5.00/0.00) lat (ms,95%): 0.00 err/s: 0.00 reconn/s: 0.00 SQL statistics: queries performed: read: 0 write: 31 ----寫入的次數 other: 0 total: 31 transactions: 1000000 (157519.17 per sec.) ----事務數(每秒事務數)【TPC】 queries: 31 (4.88 per sec.)----[QPS] ignored errors: 0 (0.00 per sec.) reconnects: 0 (0.00 per sec.) General statistics: total time: 6.3446s ----總共耗費時間 total number of events: 1000000 ----總共寫入的事務數量 Latency (ms): min: 0.00 ---最小時間 avg: 0.01 ----平均耗費時間 max: 264.84 ----最大時間 95th percentile: 0.00 ----95%的用戶可能耗費的時間 [延時] sum: 5975.17 ----總共耗費的時間 Threads fairness: events (avg/stddev): 1000000.0000/0.00 ----#平均每個線程完成envet的次數.stddev:標准偏差,表示每個表中寫入的數據量的相比距離平均數的偏差值 execution time (avg/stddev): 5.9752/0.00 ----#平均每個線程平均耗時,后一個值是標准差