0. TPC-H是啥
TPC-H是TPC提供的一個benchmark,用來模擬一個現實中的商業應用,可以生成一堆虛構的數據,且自帶一些查詢,可以導入到各種數據庫中來模擬現實需求,檢查性能。
具體是怎樣的數據見:http://www.tpc.org/tpch/spec/tpch2.16.0.pdf
1. 獲取文件
首先到官網 http://www.tpc.org/tpch/ 在右邊的 DBGEN & Reference Data Set 下載到下面那個.zip,然后自己選一個路徑解壓過去。
2. 修改 makefile
在解壓的文件夾下面cd到dbgen下,找到makefile.suite。
~/tpch_2_16_1$ cd dbgen
~/tpch_2_16_1/dbgen$ vim makefile.suite
把103~112行左右改成這個樣子
CC = gcc # Current values for DATABASE are: INFORMIX, DB2, TDAT (Teradata) # SQLSERVER, SYBASE, ORACLE, VECTORWISE # Current values for MACHINE are: ATT, DOS, HP, IBM, ICL, MVS, # SGI, SUN, U2200, VMS, LINUX, WIN32 # Current values for WORKLOAD are: TPCH DATABASE = MYSQL MACHINE = LINUX WORKLOAD = TPCH #
改動的地方分別是:
- 設定C語言編譯器為gcc(如果你用的是其他的編譯器就改成其他對應名字)
- DATABASE設為MYSQL(注意注釋里寫的提供的數據庫格式沒有mysql,所以等一下要自己寫一個格式,見步驟3)
- MACHINE = LINUX 和 WORKLOAD = TPCH 就不用說啥意思了……
改好之后保存為makefile,這樣才好用make命令。
3. 修改tpcd.h
// 其實這一步好像沒什么用 = = // 不過你上面把DATABASE設成了MYSQL的話就不要跳過這一步,不然編譯不了。 // 或者上面那步也可以設成SQLSERVER這步就不用管了
之前說了官方的生成程序沒有mysql的格式,所以我們要自己寫一個,打開tpcd.h,找一個空白的地方寫上
#ifdef MYSQL #define GEN_QUERY_PLAN "" #define START_TRAN "START TRANSACTION" #define END_TRAN "COMMIT" #define SET_OUTPUT "" #define SET_ROWCOUNT "limit %d;\n" #define SET_DBASE "use %s;\n" #endif
這樣就定義了一個MYSQL的腳本格式可以用了。
4. 生成dbgen
接下來make,生成數據生成腳本dbgen.
~/tpch_2_16_1/dbgen$ make
這個過程中會有一些關於數據類型的警告,一般可以無視。
make完dbgen目錄下之后就會多出很多.o(等到你所有事都干完確定這些沒有用了不想留着就make clean,或者直接整個文件夾刪掉……)和一個叫dbgen的文件
5. 生成tbl數據文件
接下來要用dbgen生成數據,一共會生成8個表(.tbl)。
查看README里面有命令行參數解說,這里我們在dbgen目錄下用
./dbgen -s 1
-s 1 表示生成1G的數據 (如果你之前曾經嘗試過生成數據,最好先make clean,再重新make,接着到這步加上-f覆蓋掉)
生成之后可以用head命令檢查一下tbl們,會看到每一行都有一些用“|”隔開的字段。
6. 修改初始化腳本使mySQL可用
壓縮包里自帶兩個腳本:
- dss.ddl:用來建表
- dss.ri:關聯表中primary key和foreign key。
不過這些腳本不能直接在mySQL里用(看README就知道人家根本沒考慮過mySQL……),要修改。
dss.ddl的開頭需要加上一些給MySQL建立數據庫連接用的指令。改完之后是這樣:
https://gist.github.com/joyeec9h3/9617329
dss.ri 的情況復雜一些,因為MySQL里添加外鍵要指明鍵的名字,所以每個加外鍵的指令都需要改。前面也有幾行MySQL不兼容的東西,改完之后是這樣:
https://gist.github.com/joyeec9h3/9617302
如果要直接用這兩個腳本請注意:
- dss.ddl開頭的tpch是數據庫的名字,你也可以換成其他名字,但如果改了,dss.ri里凡是提到“tpch”的地方也要改成對應的數據庫名字。
- 這兩個腳本用的表名和field名均和tpch文檔一致,但tpch自帶的測試貌似用了另外的表名。
以下可選,但本教程后面的步驟沒有考慮這步
鑒於tpch自帶的測試用的表名是小寫的,而dss.ddl里面的表名是大寫的,我們最好也改成小寫……
用vim打開dss.ddl,執行
:%s/TABLE\(.*\)/TABLE\L\1
就可以了。
如果你要事后改,就進到mySQL里,USE tpch,然后用類似於
alter table CUSTOMER rename to customer;
這樣的語句改就行了。嫌一個個打麻煩的話就寫腳本吧~
7. 建表
打開mysql,執行
mysql> \. ~/tpch_2_16_1/dbgen/dss.ddl
后面那部分是dss.ddl的路徑,要按照你的實際存放地址修改
然后可以用
mysql> SHOW DATABASES;
看到有一個叫tpch的數據庫,像這樣:
就說明建庫成功了。(記得打分號,我老是忘記打分號……)
再執行
mysql> USE tpch; mysql> SHOW TABLES;
可以看到生成的8個表就說明建表成功,像這樣
下一步需要添加外鍵和主鍵,執行
mysql> \. ~/tpch_2_16_1/dbgen/dss.ri
同樣記得dss.ri的路徑要改成你的實際存放路徑。
如果想看看外鍵和主鍵是否添加成功,有沒有添加對,可以執行 SHOW CREATE TABLE 表名(覺得默認格式很礙眼可以試試看加上\G垂直打印),像這樣:
可以看到有哪些限制加進去了。
做完以上步驟之后光有一堆表和限制,里面是沒有數據的,需要從之前生成的.tbl里將實際的數據導入進來。
8. 寫個導入tbl文件的腳本
你也可以進到mysql然后寫一堆類似於
LOAD DATA LOCAL INFILE '/home/joyeecheung/tpch_2_16_1/dbgen/supplier.tbl' INTO TABLE SUPPLIER FIELDS TERMINATED BY '|' LINES TERMINATED BY '|\n';
的東西,不過實在太龜毛了……所以還是寫一個bash腳本自動生成這些語句好了。
// 懶得運行腳本生成指令or需要添加外鍵主鍵的請往后跳一點直接看成品……
// 不懂bash的人可以看下面,懂的大牛看了這么弱的腳本請別來pia我……
在dbgen目錄下新建一個load.sh(或者隨便什么名字),把這些東西復制進去
https://gist.github.com/joyeec9h3/9619766
以load.sh為名保存到dbgen目錄下,然后執行
sh load.sh
同目錄下就會生成一個loaddata.sql,里面是從8個tbl里導入數據的sql指令。
注意如果需要導入外鍵和主鍵,要根據各個表的依賴關系調整一下導入各個文件的順序。(其實就是拓撲排序口桀口桀……不過也就是把八個代碼塊調整一下順序而已,這么點工作量就不寫代碼了)
成品看這里,可以直接復制保存到dbgen目錄下進行下一步(要直接用記得替換成你的保存路徑):
https://gist.github.com/joyeec9h3/9619336
9. 執行腳本導入數據
在dbgen目錄下運行
mysql --local-infile -u root -p < loaddata.sql
記得要加那個 --local-infile,因為MySQL為了安全默認是把從外部文件導入數據的功能關掉的,要導入的話就必須在啟動MySQL的時候打開這個功能。
接下來可以喝杯茶等導入。如果你覺得它好像死在那里了,可以再開一個終端,登陸MySQL,用SHOW processlist;看看它在干嘛。
如果你好奇導入多少了,可以用SHOW TABLE STATUS FROM tpch; 看看目前每個表都導入了多少行,對照一下文檔里寫的1G數據量每個表總共會有幾行數據,心里就有譜了。
10. 檢查導入結果
按照前面的步驟,如果你不加foreign key和primary key關聯的話,導入還是挺快的……
我的本本CPU是i7-2670QM@2.20GHz,虛擬機分配了2個核和2G內存,日立的硬盤分了20G給它(現在一看貌似不夠用啊囧),大概7分鍾左右就能導入完的樣子。如果加了外鍵和主鍵速度會顯著降低,大約是60多分鍾,而且貌似越到后面速度越慢。
導入完了之后可以用
SHOW TABLE STATUS FROM tpch;
看看是不是都導入進去了,對照一下文檔的13頁,看看每個表行數有沒有差太遠,我測試是都導進去了,查詢結果如下:
mysql> SHOW TABLE STATUS FROM tpch\G; *************************** 1. row *************************** Name: CUSTOMER Engine: InnoDB Version: 10 Row_format: Compact Rows: 149842 Avg_row_length: 192 Data_length: 28884992 Max_data_length: 0 Index_length: 3686400 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 2. row *************************** Name: LINEITEM Engine: InnoDB Version: 10 Row_format: Compact Rows: 6009452 Avg_row_length: 147 Data_length: 883949568 Max_data_length: 0 Index_length: 218103808 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 3. row *************************** Name: NATION Engine: InnoDB Version: 10 Row_format: Compact Rows: 25 Avg_row_length: 655 Data_length: 16384 Max_data_length: 0 Index_length: 16384 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 4. row *************************** Name: ORDERS Engine: InnoDB Version: 10 Row_format: Compact Rows: 1491770 Avg_row_length: 131 Data_length: 196804608 Max_data_length: 0 Index_length: 39403520 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 5. row *************************** Name: PART Engine: InnoDB Version: 10 Row_format: Compact Rows: 200806 Avg_row_length: 164 Data_length: 33095680 Max_data_length: 0 Index_length: 0 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 6. row *************************** Name: PARTSUPP Engine: InnoDB Version: 10 Row_format: Compact Rows: 778800 Avg_row_length: 267 Data_length: 208388096 Max_data_length: 0 Index_length: 20496384 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 7. row *************************** Name: REGION Engine: InnoDB Version: 10 Row_format: Compact Rows: 5 Avg_row_length: 3276 Data_length: 16384 Max_data_length: 0 Index_length: 0 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: *************************** 8. row *************************** Name: SUPPLIER Engine: InnoDB Version: 10 Row_format: Compact Rows: 9594 Avg_row_length: 274 Data_length: 2637824 Max_data_length: 0 Index_length: 278528 Data_free: 130023424 Auto_increment: NULL Create_time: 2014-03-18 18:43:43 Update_time: NULL Check_time: NULL Collation: latin1_swedish_ci Checksum: NULL Create_options: Comment: 8 rows in set (0.81 sec)
還可以用 SELECT * FROM 表名 LIMIT 數量; 來從表抓幾個數據看:
參考鏈接
http://www.pilhokim.com/index.php?title=Project/EFIM/TPC-H&oldid=90509#Setup_MySQL
http://imysql.cn/2012/12/21/tpch-for-mysql-manual.html
http://my2iu.blogspot.com/2009/01/running-tpc-h-queries-on-mysql.html