MySQLとDrizzleのベンチマーク
先日インストールしたDrizzleの簡単な性能評価をしてみました.
速度はもちろんですが,どれくらいMySQLと互換性があるか調べたかったのです.
Drizzle自体は,先日インストールした通りです.
DrizzleをFreeBSDにインストールしてみた - なぜか数学者にはワイン好きが多い
MySQLは,普通にMySQLのサイトからFreeBSD用のMySQL 5.1をダウンロードして,
MySQL :: Download MySQL Community Server
BINARY-INSTALLに従ってインストールしました.
まずDrizzleを立ち上げます.
# drizzled --datadir=/tmp/drizzle.data/ -u tetu-s --console-enable --port=3306 InnoDB: The InnoDB memory heap is disabled InnoDB: Neither mutexes nor rw_locks use GCC atomic builtins. InnoDB: highest supported file format is Barracuda. InnoDB: The log sequence number in ibdata files does not match InnoDB: the log sequence number in the ib_logfiles! InnoDB: Database was not shut down normally! InnoDB: Starting crash recovery. InnoDB: Reading tablespace information from the .ibd files... InnoDB: Restoring possible half-written data pages from the doublewrite InnoDB: buffer... InnoDB: Last MySQL binlog file position 0 0, file name UNUSED InnoDB Plugin 1.0.4 started; log sequence number 5179208 Listening on 0.0.0.0:3306 Listening on 0.0.0.0:4427 drizzled: Forcing close of thread 0 user: '' drizzled: ready for connections. Version: '2009.12.1251' Source distribution (drizzle)
そして別なターミナルでDrizzleクライアントを立ち上げて,テストに使うデータベース「test」を作ります.
> drizzle Welcome to the Drizzle client.. Commands end with ; or \g. Your Drizzle connection id is 3 Server version: 2009.12.1251 Source distribution (drizzle) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. drizzle> show databases; +--------------------+ | Database | +--------------------+ | information_schema | +--------------------+ 1 row in set (0 sec) drizzle> CREATE DATABASE test; Query OK, 1 row affected (0.46 sec) drizzle>
コマンドはmysqlクライアントと同じです,ここまでは.
次にMySQLを立ち上げます.
# /usr/local/mysql/bin/mysqld_safe --user=mysql mysqld_safe Logging to '/usr/local/mysql/data/localhost.err'. mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/data
そして同様に,テスト用のデータベース「test」を作ります.
# /usr/local/mysql/bin/mysql Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.1.41 MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | +--------------------+ 2 rows in set (0.00 sec) mysql> CREATE DATABASE test; Query OK, 1 row affected (0.04 sec)
サーバの準備が出来たので,プログラムを作ります.
以前と同様に,
C++によるMySQLの高速アクセス予備実験 - なぜか数学者にはワイン好きが多い
c++とmysql++を使います.
DrizzleはMySQLプロトコルをサポートしているので,プログラムは改造無しで一つで大丈夫と信じて,OpenMPでスレッド対応にした以下のものだけを使います.
#include <omp.h> #include <stdlib.h> #include <mysql++.h> using namespace std; using namespace mysqlpp; static const int MAX_ROW=20000; // DBにINSERTする行数 void Abort(string e) { cout<<e<<endl; exit(1); } int database_reset(Connection &db_conn) { Query query = db_conn.query(); query<<"DROP TABLE IF EXISTS bench"; // テーブルがあったら消して作り直す if(query.execute()==false) Abort(query.error()); query<<"CREATE TABLE bench (mykey INT NOT NULL, value VARCHAR(255) NOT NULL, PRIMARY KEY (mykey)) ENGINE = INNODB;"; if(query.execute()==false) Abort(query.error()); return(0); } int generate_data_table(vector<string> &table) { for(int key=0;key<MAX_ROW;++key) { string val="val:"; for(int j=0;j<rand()%200+1;++j) // 最大で200文字のデータと仮定 { val+= (char)(48+rand()%10); // アスキーコードで0から9の数字の文字を作る } table.at(key)=val; } return(0); } int insert_data_table(vector<Connection> &db_conn, vector<string> &table) { #pragma omp parallel for // OpenMP対応 for(int key=0;key<MAX_ROW;++key) { ostringstream ost; Query query = db_conn.at(omp_get_thread_num()).query(); // 各スレッド用のコネクションを使う query<<"INSERT INTO bench (mykey, value) VALUES ("<<key<<",'"<<table.at(key)<<"')"; ost<<"cannot insert test data("<<key<<","<<table.at(key)<<")"; if(query.execute()==false) Abort(ost.str()); } return(0); } int main() { srand(0); // 同じ乱数を生成するために同じシードを使う vector<string> table(MAX_ROW); vector<Connection> conn(false); conn.resize(atoi(getenv("OMP_NUM_THREADS"))); // 同時スレッド数の数だけコネクションを準備 for(int i=0;i<conn.size();++i) { if(conn[i].connect("test", "127.0.0.1", "nobody", "")!=true) { Abort("cannot connect db"); } } database_reset(conn[0]); // テーブルの初期化は一回でいいので generate_data_table(table); insert_data_table(conn, table); return(0); }
このプログラムのコンパイルは,FreeBSDではこんな感じです.
> c++ mysql-test.cc -fopenmp -I/usr/local/mysql/include -I/usr/local/include/mysql++/ -L/usr/local/mysql/lib -L/usr/local/lib -lmysqlpp
まずMySQLで実行してみます.
> setenv OMP_NUM_THREADS 1 > time ./a.out 0.504u 0.376s 0:17.12 5.0% 34+1189k 0+0io 0pf+0w > setenv OMP_NUM_THREADS 10 > time ./a.out 0.624u 0.327s 0:08.29 11.3% 32+1136k 0+0io 0pf+0w
次,Drizzle行きます.
> setenv OMP_NUM_THREADS 1 > time ./a.out 0.536u 0.345s 0:17.08 5.0% 26+928k 0+0io 0pf+0w > setenv OMP_NUM_THREADS 10 > time ./a.out 0.560u 0.373s 0:07.27 12.7% 29+1031k 0+0io 0pf+0w
速度的には,ほぼ同じという結果が得られました.
どちらもスレッド数が1では約17秒,スレッド数が10では約7〜8秒でした.
特にDrizzleが高速だったということは無いですが,逆に言うと,Drizzleが既にMySQL相当の速度が出たと考えるべきでしょうか.
DBにinsertした内容は同一でした.
ただし,mysqldumpでDrizzleのダンプを取ろうとするとエラーが出てしまって,drizzledumpというプログラムを使って比べました.