利用TPC-H為MYSQL生成數據
導言
這篇文章是看了joyee寫的TPC-H數據導入MySQL教程以及另一篇網上的MySQL TPCH測試工具簡要手冊 后寫的,有些內容是完全轉載自以上兩篇文章的,這里我寫這篇文章主要寫下自己的歸納和更改。
TPC-H簡介
TCP-H是一個決策支持的測試基准,由一系列面向商務應用的查詢和並發數據修改組成,其選擇的查詢和組成數據庫的數據在商業上都具有廣泛的代表性並且易於實現。該基准描述了決策支持系統的三個方面:分析大量的數據,執行高復雜度的查詢,回答關鍵的商業問題。
我主要是想用TPC-H生成數據庫樣本,用於進行數據庫實驗。但是TPC-H是不支持為MYSQL生成數據的,所以我們需要對它的配置文件進行一些“魔改”。
TPC-H的安裝包可以從官網免費獲取。
過程
1、解壓和編譯
解壓tpch文件,進入dbgen目錄。
首先,我們需要更改TPC-H編譯文件,
cp makefile.suite makefile
接着修改makefile文件
將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添加依賴。
修改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
修改完編譯配置文件,我們可以編譯出程序。
命令行執行make
這個過程中會有一些關於數據類型的警告,無視它。
make完dbgen目錄下之后就會多出很多.o 文件,dbgen、qgen可執行程序,dss.ri,dss.dll文件。
2.生成數據
dbgen:數據生成工具。可以用該工具生成tpch相關表數據。
我們使用dbgen生成數據,共生成8個表(.tbl)。
./dbgen -s 1
-s 1表示生產1G數據,我們也可以根據我們需要更改大小。
3.修改相關腳本
接着,
dss.ddl – DSS庫初始化DDL腳本
dss.ri – DSS數據表創建索引、外鍵腳本
由於我們用的是MYSQL,所以需要對這些腳本進行適當修改。
dss.dll 需要在開頭添加
drop database tpch;
create database tpch;
use tpch;
成品文件 https://gist.github.com/MR-HOWE/9cd5c3438a1e2c79c66d2526e3ae30e3
dss.ri 的情況復雜一些。
首先,更改第6~13行命令(原來的與MYSQL不兼容),在所有的SQL注釋符 “--” 后面再加一個空格
-- ALTER TABLE TPCD.REGION DROP PRIMARY KEY;
-- ALTER TABLE TPCD.NATION DROP PRIMARY KEY;
-- ALTER TABLE TPCD.PART DROP PRIMARY KEY;
-- ALTER TABLE TPCD.SUPPLIER DROP PRIMARY KEY;
-- ALTER TABLE TPCD.PARTSUPP DROP PRIMARY KEY;
-- ALTER TABLE TPCD.ORDERS DROP PRIMARY KEY;
-- ALTER TABLE TPCD.LINEITEM DROP PRIMARY KEY;
-- ALTER TABLE TPCD.CUSTOMER DROP PRIMARY KEY;
接着,因為MySQL里添加外鍵要指明鍵的名字,所以每個加外鍵的指令都需要改。
修改第25行:
ADD FOREIGN KEY NATION_FK1 (N_REGIONKEY) references TPCD.REGION;
=>
ADD FOREIGN KEY NATION_FK1 (N_REGIONKEY) references TPCD.REGION(R_REGIONKEY);
修改第40行:
ADD FOREIGN KEY SUPPLIER_FK1 (S_NATIONKEY) references TPCD.NATION;
=>
ADD FOREIGN KEY SUPPLIER_FK1 (S_NATIONKEY) references TPCD.NATION(N_NATIONKEY);
修改第55行:
ADD FOREIGN KEY CUSTOMER_FK1 (C_NATIONKEY) references TPCD.NATION;
=>
ADD FOREIGN KEY CUSTOMER_FK1 (C_NATIONKEY) references TPCD.NATION(N_NATIONKEY);
修改第73行:
ADD FOREIGN KEY PARTSUPP_FK1 (PS_SUPPKEY) references TPCD.SUPPLIER;
=>
ADD FOREIGN KEY PARTSUPP_FK1 (PS_SUPPKEY) references TPCD.SUPPLIER(S_SUPPKEY);
修改第78行:
ADD FOREIGN KEY PARTSUPP_FK2 (PS_PARTKEY) references TPCD.PART;
=>
ADD FOREIGN KEY PARTSUPP_FK2 (PS_PARTKEY) references TPCD.PART(P_PARTKEY);
修改第84行:
ADD FOREIGN KEY ORDERS_FK1 (O_CUSTKEY) references TPCD.CUSTOMER;
=>
ADD FOREIGN KEY ORDERS_FK1 (O_CUSTKEY) references TPCD.CUSTOMER(C_CUSTKEY);
修改第90行:
ADD FOREIGN KEY LINEITEM_FK1 (L_ORDERKEY) references TPCD.ORDERS;
=>
ADD FOREIGN KEY LINEITEM_FK1 (L_ORDERKEY) references TPCD.ORDERS(O_ORDERKEY);
修改第96行:
TPCD.PARTSUPP;
=>
TPCD.PARTSUPP(PS_PARTKEY,PS_SUPPKEY);
另外,由於TPC-H生成的表名是大寫的,基於MYSQL的標准,我們最好把表名修改為小寫的,因此在文件末尾添加:
ALTER TABLE CUSTOMER rename to customer;
ALTER TABLE LINEITEM rename to lineitem;
ALTER TABLE NATION rename to nation;
ALTER TABLE ORDERS rename to orders;
ALTER TABLE PART rename to part;
ALTER TABLE PARTSUPP rename to partsupp;
ALTER TABLE REGION rename to region;
ALTER TABLE SUPPLIER rename to supplier;
成品文件 https://gist.github.com/MR-HOWE/18dc736352183f3a3447db8f49b397d1
接着打開mysql,執行
mysql> \. 路徑/dss.ddl
然后可以用
mysql> SHOW DATABASES;
如果看到tcph數據庫,所以建庫成功。
再執行
mysql> USE tpch;
mysql> SHOW TABLES;
可以看到生成的8個表就說明建表成功。
下一步需要添加外鍵和主鍵,執行
mysql> \. 路徑/dss.ri
4.導入數據
現在,數據庫tcph只是建好了表,設定好了主鍵和外鍵,內容還是為空。我們需要將之前生成的tbl文件導入。
8個表就需要輸入執行8條命令,這里joyee寫了一個腳本,可以方便的生成sql命令,腳本如下(這里表示要向大佬學習,發揮“偷懶精神”)
#!/bin/bash
write_to_file()
{
file="loaddata.sql"
if [ ! -f "$file" ] ; then
touch "$file"
fi
echo 'USE tpch;' >> $file
DIR=`pwd`
for tbl in `ls *.tbl`; do
table=$(echo "${tbl%.*}" | tr '[:lower:]' '[:upper:]')
echo "LOAD DATA LOCAL INFILE '$DIR/$tbl' INTO TABLE $table" >> $file
echo "FIELDS TERMINATED BY '|' LINES TERMINATED BY '|\n';" >> $file
done
}
write_to_file
這里由於我之前把表名改為小寫了,所以我們不需要大寫表名。同時,因為有外鍵約束,表的導入需要安裝約束順序來,為了方便導入,我們可以先把外鍵約束關了,導入完表再重新打開外鍵約束,代碼如下:
#!/bin/bash
write_to_file()
{
file="loaddata.sql"
if [ ! -f "$file" ] ; then
touch "$file"
fi
echo 'USE tpch;' >> $file
echo 'SET FOREIGN_KEY_CHECKS=0;' >> $file
DIR=`pwd`
for tbl in `ls *.tbl`; do
table=$(echo "${tbl%.*}")
echo "LOAD DATA LOCAL INFILE '$DIR/$tbl' INTO TABLE $table" >> $file
echo "FIELDS TERMINATED BY '|' LINES TERMINATED BY '|\n';" >> $file
done
echo 'SET FOREIGN_KEY_CHECKS=1;' >> $file
}
write_to_file
將以上代碼保存到dbgen目錄下,保存為“load.sh”,然后執行
sh load.sh
同目錄下就會生成一個loaddata.sql,里面是從8個tbl里導入數據的sql指令。
在dbgen目錄下運行
mysql -u root -p < loaddata.sql
即可。
(這里如果運行有問題看看試試joyee說的加上 --local-infile。mysql --local-infile -u root -p < loaddata.sql
)