MySQLでTPC-Hベンチマークを実行する

DSS (Decision Support System) のベンチマークであるTPC-HMySQLで実行してみます。

HammerDB というTPC-Hを実行できるベンチマークツールも存在するのですが、今回は公式に配布されるデータロードプログラムのDBGENとクエリ作成プログラムのQGENを使用します。

環境

前提

  • MySQLがインストールされていること
  • mysqldが動いてること

手順

TPC-H用のデータベースとユーザの作成

TPC-H用のデータベースtpchとクエリを実行するユーザーtpchを作成します。 わかりやすさのためtpchとしていますが、別に何でもいいと思います。
ユーザーtpchにはデータベースtpchの権限を与えておきます。

$ mysql -u root -p

mysql> CREATE DATABASE tpch;
Query OK, 1 row affected (0.00 sec)

mysql> CREATE USER 'tpch'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT ALL ON tpch.* to 'tpch'@'localhost';
Query OK, 0 rows affected (0.00 sec)

DBGEN, QGENのセットアップ

DBGENとQGENは公式ページ TPC-H - Homepage の右のリンクからダウンロードできますが、MySQLで実行するには何点かの修正パッチが必要です。
ダウンロードとパッチの適用などをしてくれるスクリプトinstall-dbgen.shを書いたので、それを用います。 install-dbgen.shが行うことは以下の通りです。

  • DBGENのダウンロードと展開
  • dss.ddl, dss.ri, tpcd.hに対してパッチを適用し、その後dbgen, qgenコンパイル
  • dbgen, qgenのラッパースクリプトの設置

DBGENのダンロード先とラッパースクリプトの設置先はそれぞれシェル変数SRC_DIRBIN_DIRで指定します。
今回はSRC_DIR~/srcBIN_DIR~/binを指定します。

$ cd ~/src
$ git clone git://github.com/itiut/tpch-mysql
$ BIN_DIR=~/bin SRC_DIR=~/src ./tpch-mysql/install-dbgen.sh

install-dbgen.shのソースはこちらから。itiut/tpch-mysql
修正点は以下の通りです。

  • データベース名とテーブル名を大文字から小文字に変更 (dss.ddl, dss.ri)
  • コメントの文法を修正 (dss.ri)
  • 外部キー作成クエリに参照先のカラム名を追加 (dss.ri)
  • MySQL用のヘッダ定義を追加 (tpcd.h)
  • クエリのテンプレートをMySQLの文法に修正 (queries/*.sql)

通常dbgenqgenを実行するときには辞書ファイルやクエリテンプレートを指定しなければいけないのですが、ラッパースクリプトではその辺の指定をしなくても済むようにしています。 tpch-mysql/queriesにあるクエリテンプレートとSRC_DIRにダウンロードしたDBGENをそのまま使うので、変更や削除はしないで下さい。

テーブルの作成

dbgenと同じディレクトリにある、テーブル作成用のクエリdss.ddlを実行してテーブルを作成します。

$ cd ~/src/tpch_2_17_0/dbgen
$ mysql -u tpch -D tpch < dss.ddl

dbgenを用いてデータを作成

BIN_DIRに指定したディレクトリが環境変数PATH中にあれば、dbgenが使えます。
dbgenの基本的な使い方としては、-sオプションでScale Factorというデータのサイズの指標を変更します。Scale Factorが大きいときには、データを分割して作成することもできます。
データは拡張子.tblのファイルとして作成されます。

$ dbgen -s 1
$ ls *.tbl
customer.tbl  lineitem.tbl  nation.tbl  orders.tbl  partsupp.tbl  part.tbl  region.tbl  supplier.tbl

データベースにデータをロード

作成したデータのファイル名から拡張子を除いたものが同じ名前のテーブルに対応しているので、対応するテーブルにデータをロードします。

$ for tbl_file in *.tbl; do mysql -u tpch -D tpch -e "LOAD DATA LOCAL INFILE '$tbl_file' INTO TABLE $(basename $tbl_file .tbl) FIELDS TERMINATED by '|' LINES TERMINATED BY '\n';"; done

インデックスを作成

dbgenと同じディレクトリにある、インデックス作成用のクエリdss.riを実行してインデックスを作成します。

$ mysql -u tpch -D tpch < dss.ri

qgenを用いてクエリを作成

qgen-sオプションでScale Factorを指定します。
1~22のクエリ番号を指定してクエリを個別に作成できます。

$ for i in $(seq 1 22); do qgen -s 1 $i > $i.sql; done
$ ls *.sql
10.sql  11.sql  12.sql  13.sql  14.sql  15.sql  16.sql  17.sql  18.sql  19.sql  1.sql  20.sql  21.sql  22.sql  2.sql  3.sql  4.sql  5.sql  6.sql  7.sql  8.sql  9.sql

後はこれらのクエリを

$ mysql -u tpch -D tpch < 1.sql

などで実行するだけです。

平成26年度データベーススペシャリスト試験に合格した

やったぜ。

f:id:itiut:20140620125007p:plain

とはいえ準備不足だったためあまり点数は高くないので、これからもっと精進します。

研究室の同期向けにターミナルの勉強会を開いた

4月から新しい研究室に変わってリモートで作業する機会が増えたので、自分自身の復習も兼ねてターミナルにあまり慣れてないであろう研究室の同期向けにターミナルの勉強会を開きました。
参加者は私を含めてM1とM2合わせて9人で、内容はbashとtmuxの基本操作・設定をデモを交えつつやり、最後に~/.ssh/configを使うとsshコマンドが楽になるということを説明しました。

スライドはこちら。
黒い画面入門

f:id:itiut:20140619155102p:plain

勉強会中の質問とか感想とか

  • 意外とbashの行頭・行末移動のC-aC-eのコマンドが覚えられない
    • キーボード上でaが左、eが右にあるのを行頭・行末と対応させると覚えやすい
  • whatis emacsは哲学
  • コマンドの実行回数ランキングの上位が1文字になっててウケる
  • rm -iにしてても結局確認せずにy押してEnterしちゃう
    • ファイルの内容確認して重要そうだったら警告してくれるコマンドがあったら幸せになれそう
  • tmuxの|でペイン縦に分割、-でペインを横に分割は直感的でわかりやすい
  • 多段sshは全然知られてなかった
  • tmuxの発音は「ティーマックス」だった?
    • 今までずっと「ティーミュックス」と呼んでた

スライドの作成環境

PowerPointを窓から投げ捨てたいのですが、良さそうな移行先が見つかってません。

前に使ったglide.soというgist上のmarkdownをスライドショーにしてくれるサービスがダウンしてて使えなかったので、今回のスライドはRemarkを使って作ったのですが、結構使いやすかったです。

$ python -m SimpleHTTPServerすればローカル環境だけでプレビューできてとても楽です。
ただしテンプレートらしきものはないのでcssを少しカスタマイズしないといけないし、htmlの<textarea>にmarkdownを直書きするのは少しキモいです。

しばらくはRemarkを使ってみようと思います。

InnoDBの共有テーブルスペースにrawデバイスを使う

すごくハマったのでメモ。 公式ドキュメントに手順が載っているが、これだけではできなかった。

MySQL :: MySQL 5.6 Reference Manual :: 14.5.8 Using Raw Disk Partitions for the Shared Tablespace

環境

  • MySQL 5.6.19
    • ソースからインストール
    • basedir: /opt/mysql
    • datadir: /var/lib/mysql
  • 使うデバイス: /dev/sdb1
  • mysqldを動かすユーザー: mysql

手順

1. innodb_file_per_tableを無効に

5.6.6 以降はデフォルトでinnodb_file_per_tableが有効になっていて、テーブルごとにファイルを作ってしまう。 /etc/my.cnfを開いて[mysqld]セクションに無効にする設定を追加しておく。

またこの時点ではinnodb_data_file_pathはデフォルト値に設定しておく。 rawデバイス用の設定にするとmysql_install_dbでデータディレクトリを初期化したときにエラーが生じ、rootパスワードが勝手に設定されてmysqlにログインできなかった。

[mysqld]
innodb_file_per_table=OFF
innodb_data_file_path=ibdata1:12M:autoextend

2. mysql_install_dbでデータディレクトリの初期化

$ sudo /opt/mysql/scripts/mysql_install_db --user=mysql --datadir=/var/lib/mysql

必要に応じて--datadirオプションを付けてデータディレクトリを指定する。

3. mysqlデータベース中のテーブルのダンプと削除

ibdata1中にはmysqlデータベース中のいくつかのテーブルが含まれている。5.6 以前ではibdata1が削除されるとそれらのテーブルは再び作られるが、5.6 では再び作られないらしい。
innodb - Cannot open table mysql/innodb_index_stats - Database Administrators Stack Exchange

なのでこれらのテーブルをダンプしておいて、後でリストアする。 これらのテーブルを復元しないでおくとInnoDB: Error: Table "mysql"."innodb_table_stats" not found.というようなエラーが大量に出ていた。

mysqldを起動してテーブルをダンプして削除。その後mysqldを停止。

$ sudo service mysql.server start

$ mysqldump -u root mysql \
innodb_index_stats \
innodb_table_stats \
slave_master_info \
slave_relay_log_info \
slave_worker_info \
> mysql_innodb_tables.sql

$ mysql -u root -D mysql -e "DROP TABLE innodb_index_stats, innodb_table_stats, slave_master_info, slave_relay_log_info, slave_worker_info"

$ sudo service mysql.server stop

4. ログファイルの削除

ドキュメントには書かれていなかったが、ib_logfile0などのログファイルが存在するとログが書き込めないというエラーが生じた。

$ sudo rm /var/lib/mysql/ib_logfile*

5. rawデバイスの初期化のための設定

ここからやっとドキュメントの手順開始。
/etc/my.cnfを開いてinnodb_data_home_dirinnodb_data_file_pathを設定する。

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/sdb1:300Gnewraw

使うデバイスの所有者がmysqldを動かすユーザーと同じでないとデバイスを開けないので、所有者を変更しておく。

$ sudo chown mysql:mysql /dev/sdb1

6. rawデバイスの初期化

mysqldを起動するとrawデバイスの初期化が始まる。大きい容量を指定していると長い時間がかかる。
初期化が終わったら何もせずにmysqlを停止させる。

$ sudo service mysql.server start && sudo service mysql.server stop

7. rawデバイス用の設定

/etc/my.cnfを開いてinnodb_data_file_pathの値がnewrawであったところをrawに変更する。

[mysqld]
innodb_data_home_dir=
innodb_data_file_path=/dev/sdb1:300Graw

8. ダンプしたテーブルのリストア

mysqldを起動してさっきダンプしたテーブルをリストアする。

$ sudo service mysql.server start

$ mysql -u root -D mysql < mysql_innodb_tables.sql

以上で完了。

KVM上のVirtIOを使うWindowsでディスクアクセス速度を測定してみた

前回に引き続きKVMの準仮想ドライバVirtIOを使って、KVM上のWindowsでディスクアクセス速度を測定しました。 比較対象としては網羅性は無いですが、KVM上でVirtIOを使わずデフォルトのドライバを使った場合と、VirtualBox上のWindowsと、ローカルのUbuntuとで速度を測定して比較しました。

環境

ホスト環境

ハードウェア

  • CPU
  • RAM
    • DDR3 1067MHz 4GB x 2
  • HDD
    • Hitachi HTS547550A9E384 500GB 5400RPM

ソフトウェア

ゲスト環境

共通

  • 割り当てCPUコア数
    • 2
  • 割り当てメモリサイズ
    • 4096MB
  • 割り当てストレージサイズ
    • 96GB
  • ゲストOS

比較対象

  • VBox-dynamic
    • VirtualBox上で、ストレージは動的割り当て
    • AHCIタイプのストレージコントローラを使用 (デフォルト仕様)
    • ホストI/Oキャッシュは使用しない (デフォルト仕様)
  • VBox-fixed
    • VirtualBox上で、ストレージは固定割り当て
    • それ以外はVBox-dynamicと同じ
  • KVM-IDE
    • KVM上で、ストレージ固定割り当て (デフォルト仕様)
    • Disk busはIDE (デフォルト仕様)
    • I/Oキャッシュはデフォルト (有効?)
  • KVM-VirtIO
    • Disk busはVirtIO
    • それ以外はKVM-IDEと同じ
  • Local
    • ホストのローカルで測定

測定結果

KVM-VirtIOの値が非常に大きくなったので、他の値を見やすくするためKVM-VirtIOがグラフの右端で見切れるようにしてます。

考察

まずKVM-IDEKVM-VirtIOも明らかにおかしい大きな値が出ています。ローカルとゲストとで測定方法が厳密には同じではないので正確な比較ではないですが、ローカルよりもKVM-IDEKVM-VirtIOの方が大きな値を取るのは普通考えられないことです。 あまり確証はないですが、考えられる理由は2点あります。

  • KVMのホストI/Oのキャッシュがデフォルトだとオンになっていて、メモリを読み書きしていた
  • KVM (のドライバ) がものすごく頭が良くて、無意味な処理を無視していた?

一方VirtualBoxでの値はローカルの値とほぼ同等で、個人的見解としては仮想化した時のディスクアクセスのオーバーヘッドは実用上無視できると思います。

今回の測定は、デスクトップやノートPCでホストOSのWindowsを使うときにハイパーバイザとしてKVMを使うかどうかの調査も兼ねてたのですが、VirtualBoxのディスクアクセスは遅いのではないかという疑念は晴れて、VirtualBoxの使用をやめる消極的な理由はなくなりました。

KVMを使ってみた感想

  • ゲストの解像度をウィンドウサイズに合わせて変更できなかった (やり方を知らないだけかも)
  • ホストではxmodmapを使ってCapsLockを左Ctrlに変更していたのに、ゲストには反映されなかった

ディスクアクセス速度よりも使いにくさが目立ったので、KVMWindowsを仮想化するのはやめておきます。

結論

  • KVMのディスクアクセス速度はなんか悪さされて正確に測れなかった
  • VirtualBoxのディスクアクセスのオーバーヘッドは実用上無視できる (個人的見解)
  • 引き続きVirtualBoxWindowsを仮想化して使う

KVM上にVirtIOドライバを使うWindows 7をインストールする

準仮想化ドライバであるVirtIOを使うことでWindows仮想マシンのIOが速くなるか試してみたかったので、KVM上にVirtIOドライバを使うWindows 7をインストールしてみました。

凖仮想化とは、全ての命令をソフトウェアエミュレーションする完全仮想化に対して、ゲストOSなどにある程度修正を加えて、物理ハードウェア上で動かすのに近い形で動作させる仮想化のことです。Windowsの場合はカーネル自体には修正を加えれられないので、準仮想化ドライバであるVirtIOを使うことで準仮想化を実現できます。

環境

  • ホストOS: Ubuntu 14.04 64bit
  • ゲストOS: Windows 7 64bit
  • ハイパーバイザ: qemu-kvm 2.0.0
  • ドライバ: virtio-win-0.1-74.iso

インストール

kvmvirt-managerのインストール

$ sudo apt-get install qemu-kvm qemu-system libvert-bin virt-manager

libvirtdグループに入っていないと仮想マシンの操作ができないみたいですが、上のコマンドを実行するだけで現在のユーザーをlibvirtdグループに追加してくれるので、ログインし直してグループの設定を反映させます。

Windows用のVirtIOドライバをダウンロード

Vistaより新しい64bit版Windowsでは通常デジタル署名されたドライバしかインストールできません。
幸いFedoraプロジェクトでデジタル署名されたドライバを公開してくれているので、それを使います。
公式ページ WindowsGuestDrivers/Download Drivers - KVMLatest VirtIO drivers for Windows from Fedora からドライバが入ったisoファイルをダウンロードできます。

仮想マシンの作成

virt-managerを起動して、通常と同じように仮想マシンを作成します。
最後の画面でCustomize configuration before installにチェックを入れておきます。

f:id:itiut:20140602233341p:plain

設定画面が開くので、ディスクの設定でDisk busVirtioに、NICの設定でDevice modelvirtioに設定してインストールを開始します。

f:id:itiut:20140602233342p:plain

f:id:itiut:20140602233343p:plain

Windowsのインストール

インストールを進めると、初めはドライバが無いためディスクが認識されません。

f:id:itiut:20140602233344p:plain

Load driverを押すと次のような画面になります。

f:id:itiut:20140602233345p:plain

仮想マシンの設定画面からCDROMの設定を開き、Windowsのインストールisoファイルをダウンロードしておいたドライバのisoファイルに変更した後、仮想マシンの画面に戻ります。

f:id:itiut:20140602233346p:plain

Browseを押すとドライバを探す画面になるので、CDROMの中からインストールするWindowsにあったバージョンとアーキテクチャのディレクトリを選択します。

f:id:itiut:20140602233348p:plain

ドライバが見つかったので、全て選択してNextを押してインストールします。

f:id:itiut:20140602233349p:plain

ドライバのインストールが終わるとディスクが認識されます。

f:id:itiut:20140602233350p:plain

ここではWindows cannot be installed to this disk.と出てきて先に進めなくなっていますが、CDROMをWindowsインストーラisoファイルに変更し直せば先に進むことができます。

f:id:itiut:20140602233351p:plain

後は普通にインストールするだけです。

インストールして少し使ってみて思ったのですが、KVMにはVMwareVirtualBoxにはあるディスプレイの解像度の自動調整機能とかは無いんでしょうか。ググってもよくわかりませんでした。

卒論提出にあたって私はどう生きようと思うか

近況報告

本日2月7日、私は卒業論文を提出し、無事に受理されました。 発表や学位審査をまだ控えていますが、とりあえず一段落といった感じです。

昨年の10月下旬から3ヶ月少々メールやLINEなど軒並み連絡を絶っており、関係者各位におかれましては心配した方もしなかった方もいるかもしれませんが、私は生きています。

物理的に何かあったというわけではなく精神的な問題を抱え、自分の人生をどう生きるかという悩みに答えを出せずに、何も手を付けることができないという状態でした。

3ヶ月間何をしていたか

11月末までは、読書50%ゲーム50%ぐらいの時間配分で過ごしていました。 悩みの答えを求めて読書をして、読むのに疲れたらゲームで現実逃避をする、というパターンを繰り返していました。

12月に入ってからは、このままでは卒業が危ういという危機感から研究室には復帰し、卒論を進めていました。

しかし、悩みに対してある程度明確な答えを出せたのは12月の中旬になってからでした。 また、絶っていた連絡を再び取り戻そうするのにもしばらく時間がかかりました。

人生をどう生きるかという悩み

私の頭の中のどこかに必ず潜んでいる悩みが、人生をどう生きるかという悩みです。 なぜこのことについて悩むようになったかはよくわかりませんが、初めに悩むようになったのは高校2年の頃です。 普段は悩みについてほんの薄っすら考えている程度でしかありませんが、ふとした拍子に思考の中に悩みの占める割合が大きくなると、 悩みのせいで何も手を付けられず身動きが取れなくなってしまうことがあります。

何も手を付けられないほど思い悩んだことは、今回を含めると3回あります。

1回目は、高校2年の時です。 高校2年の終わりが近づくに連れて、1年後に迫る大学受験の危機感から、「偏差値の高い大学に行けばなんとかなるだろし、そうしなければならない」と思考を停止させて受験勉強に逃げ込み、悩みを先送りにするというその場しのぎの対処しかできませんでした。

2回目は、大学入学の1年後くらいです。 受験という悩みの先送り要因がなくなってしまったため、当然その悩みは立ち現れました。 入学直後は新たな大学生活に目を奪われていたため、悩みは大きくなかったものの、半年もするとしだいに悩みが大きくなり、1年後には大学生活に支障をきたすまで思い悩むようになっていました。 一人で思い悩むだけでは解決しないと思い、いろいろなことに手を出してはみたものの中途半端に終わったり失敗したりする、ということを繰り返したことを覚えています。

その過程で、自分が楽しめることをして生きる、という生き方が私にとっては一番良いのではないかと思い至りました。 自分が楽しめないことをしていても、いずれ耐えられなくなり精神的に病んでしまうということを、経験則として学んだからです。

いずれ考えを改める可能性もあるかもしれないが、ひとまずは「楽しめることをして生きる」という生き方を暫定的に掲げて生きていこうと思いました。 いろいろ手を出した中でプログラミングは楽しめたので、将来的にIT技術者として生計を立てることを念頭に置き、情報系の学科に進学したり、プログラマのアルバイトをしたりと、自分で進路を決めてきました。

プログラミングは本当に楽しかったのか

進学した学科では、電気の講義には苦しめられたものの、情報の講義はとても楽しく、概ね満足していたのだが、ここに来て3回目の悩みが生まれました。

プログラミングは確かに楽しい。しかし、プログラミングが楽しいと、他人に向かって言える自信を持てなくなってきていたのです。

なぜかというと、プログラミングが上達するにつれて、すごい人のすごさを実感できる機会がしだいに増えていき、プログラミングの実力やプログラミングに対する情熱を自分と比較して勝手に落ち込んでしまうのです。 実力という点では、ネットを見ていると、働いている年上の人はもちろん、同世代や下の世代の人でも、いろいろなプロダクトやサービスを作っているという人がたくさん見受けられます。 情熱という意味でも、寝食を除いて起きている時間は呼吸をするようにプログラミングをしている人もいるらしいし、そういう人たちに対して私もプログラミングが楽しいと胸を張って言えるかというと、言える自信はないとどうしても思ってしまうのです。

それに加えて、プログラミングの対象に、時間を忘れて熱中できるという意味での「楽しさ」を持てていなかったことに気づきました。 中間発表までの卒論にしろ、この前参加したハッカソンにしろ、これは自分が本当にやり遂げるべき仕事ではないという感覚をどこかで抱いていました。

プログラミングが楽しいと自信を持って言えなくなりつつあり、プログラミングの対象も楽しめていないのならば、「楽しめることをして生きる」という方針だと、プログラミングで生計を立てようとすることにいずれ無理が生じるだろうと思うようになり、苦悩が生じました。

私にとってのプログラミングの楽しさとは

プログラミングの楽しさがどこから来ていたのかを振り返ってみました。 するとプログラミング自体よりも、プログラミングを通して問題を解決することに楽しさを見出していたのではないか、と思うようになりました。

プログラミングを楽しいと感じたきっかけとしては、PC1台さえあれば自分の好きなモノが作れるということもさることながら、独学したての頃に競技プログラミングにハマったことも挙げられます。

また4年弱のプログラミング経験を振り返ると、自分の創造力を働かせてユニークなものを作るよりも、身の回りの不便なことを解決するものであったり、チャレンジングな課題に挑戦することの方により楽しんで取り組んでいたように思います。

その時点ではできなかったことを、プログラミングによってできるようにするという、問題解決プロセスにこそ私は楽しさを感じていたのでしょう。

どう生きようと思うか

自分が楽しいと感じることは「プログラミングによる問題解決」だとわかった今、次なる問題は、解決すべき問題は何かということです。 今回の悩みの原因になった、プログラミングの対象に情熱を持てていないということとも直接関係してくる問題です。

妥当な考えとしては、自分が解決することに情熱を持てて、かつ、それによって生計を立てるためには、社会的にも解決することに価値があるような問題なのでしょう。

「楽しいことをして生きる」という生き方の下、自分が情熱を持てる問題をプログラミングによって解決すること。 それが現時点で私が考える人生の生き方です。