業務用のサーバではありませんが、私が稼動させているMySQL4サーバーのパフォーマンスを測定してみました。
パフォーマンスを決める要素は、
●サーバ自体の設定(スレッド数・処理メモリサイズ・キャッシュなどのシステム変数)
●テーブル構造・インデックス
●クエリ
が関わってきます(※64bitカーネルなどなら、適切なビルドを用いることももちろんです)。これらが最適になるように計画して稼動を開始したので、それが狙いどおりであれば、いいパフォーマンスが出るはずです。それを確かめるのが今回の目的となります。
当方でMySQL4が稼動しているサーバは、並列でApache・Postfixも稼動していますが、小規模なサーバではそのようなケースも多いと思いますし、なにしろ相当古い計算機でもあります。いくらなんでも今時こんな低クラスのサーバは何処へ行っても買えませんが、古いものでもどの程度のパフォーマンスが出せるのか・という参考値としてご覧下さい。
■計算機のスペック
i815 / Pentium!!! 733MHz / PC133 SDRAM 512M / IDE SoftwareRAID1(MD)
Apache 1.3 / request 20,000 - 100,000
Postfix 2.1
MySQLは外部からの接続が殆どで、ローカルのApacheなどからは呼び出されていません。データベース数は3つ、うちテーブル数は5つ(MyISAM=3/InnoDB=2)、おおまかですがカラム数(フィールド数)は10-50・ロウ(レコード数)は10,000以下くらいです。
まず、サーバの稼働時間ですが、現時点で247 日, 15 時, 26 分 34 秒となっています。この間、テーブルを変更・追加などはしていませんので、パフォーマンスを測定するのには十分な期間です。
MySQLへの接続数は7,663,183、1時間あたり1,289.35接続がありました。
要求クエリ数は、毎秒1.44クエリとなっています。但し、外部からの要求は同時に連続して10以上の接続とクエリ発行が来るシステムになっているため、密度はばらつきます。
それでは、パフォーマンスの参考値としてステータスを見ていきすが、ステータスの値によって、冒頭に示したパフォーマンスを決める要素の、「どの部分は適切で・改善するならどの点なのか」を見ることが出来ます。
起動してからの総クエリ数 = 30,798,128 起動してから、これだけのクエリが送られています。この数値とステータスとの対比が判断材料の一つになります。
Created tmp disk tables 0
このステータスに限らず、メモリ&ディスクへのテンポラリテーブル作成はゼロでした。もっとも、テーブル結合をしているクエリが無いので、それも理由になります。
Handler read first 11484 ← インデックスのフルスキャン
Handler read key 17797594 ← キーに基づくレコード読み込み
Handler read next 26107115 ← キー順序での次レコード読み込み
Handler read rnd 1095850 ← テーブルのフルスキャン
ランダムでロウを選択する・カラム値とランダム値が同一のロウを得るようなクエリも投げているので、全体スキャンも発生していますが、概ねインデックスの貼り方が良かったと判断できます。
Key read requests 32669452 ← キャッシュ内からのキー読み込み要求
Key reads 210 ← ディスク内からのキー読み込み要求
キャッシュのミス率は6.4280233411934794620981092673363e-6、キーバッファが適切に割り当てられ、機能していることがわかります。
Open tables 22 ← 現在開いているテーブル数
Opened tables 145 ← これまで開いたテーブル数
稼働時間・要求数に対して、非常に小さな値ですので、テーブルキャッシュのサイズが適切に割り当てられているようです。
Table locks immediate 15361607 ← テーブルロック要求で即ロック実現
Table locks waited 7672 ← テーブルロック要求で待ちがあった
MyISAM・またはクエリで明示的にテーブルロックを指示した結果数です。専用サーバではなく、同じテーブルに対して連続して読み書きのある要求が多い中で、この結果が出たということは、クエリとテーブル設計・インデックスが適切であることを示し、この結果は良好だと考えられます。
Threads cached 15 ← 現在動作して処理待ちをしているスレッド数
Threads created 74 ← これまで作られた最大スレッド数
Linuxの場合、一つの接続を一つのスレッドで処理しているようですので、これまでの稼動の間に、並行で74の要求を処理したことがあったようです。
さらに参考までに、40のカラム・500のロウを持つテーブルに対して、varchar(255)でカーディナリティの高いカラムを昇順でソートした結果を得るための時間を出してみます(このカラムはインデックス化されています)。
SELECT * FROM `footable` ORDER BY `HOGE` ASC
このクエリの結果は、0.0026 secで得られました。
上記によって、自分の行ったテーブル設計やクエリ最適化がうまくいっていることを確認できたことが嬉しくもありますし、同時に、こんな古臭い計算機でもこれだけのパフォーマンスを叩きだすMySQLの凄まじい速さに、改めて驚きを禁じ得ません。