現場で役立つ実践ノウハウWeb開発の「べし」「べからず」(設計編)

現場で役立つ実践ノウハウWeb開発の「べし」「べからず」(設計編)

~性能を最大限に引き出すための設計・開発・運用~

永安 悟史

本記事は、技術評論社 WEB+DB PRESS Vol.63 で掲載されたものを、著者と出版社の許可を得て転載したものです。なお、一部 記述に変更のある箇所もあります。

前回の復習になりますが、データベースの開発・運用には、データベース特有の注意すべき点があります。すべてを一度に理解することは難しいですが、ここまで解説した次の3点を頭の中におきつつ、以降の解説を読んでください。

データベースを理解するための3ヵ条

  • データベースの理解は「立体的」に
  • I/Oを制する者はデータベースを制す
  • データベースは生き物である

【設計】「性能」の大枠が決まる

【べし】 データの増加量を考慮して設計すべし

「データベースは生き物である」で述べましたが、データベースの大きな特徴として「稼働しているうちにデータのサイズが大きくなってくる」という点があります。よって、データベースを設計する際には、これらのデータが、将来どれくらいの容量になるのかを見積もって設計しなければなりません。これをキャパシティプランニングと呼びます。

データ容量が想定外のサイズになった場合(あるいはそもそも何も考慮していなかった場合)、次のようなトラブルが発生する可能性があります。


  • キャッシュヒット率が少しずつ低下し、パフォーマンスが徐々に劣化する
  • 短時間で終わっていたテーブルスキャンが、長時間かかるようになって性能が劣化する
  • 共有バッファ(メモリ)への読み書きだけで高速だったトランザクション処理が、データがバッファに乗り切らなくなってディスクI/Oが発生し、パフォーマンスが急激に劣化する
  • メモリ上で完結していたソート処理が、ディスクソートに切り替わりパフォーマンスが急激に劣化する(OSのスワップと類似した処理)
  • ディスクフルによるサーバエラーによって、データベースサーバに接続できなくなる

データベースにおいては、特にこの事前のキャパシティプランニングが重要です。その理由は、一度設計したデータベースの設計(テーブル定義など)はサービス開始後には変更しづらいという点が挙げられます。

SQLを書き換えるためにはアプリケーションの修正が必要で、データが蓄積された後ではテーブル設計の修正も簡単ではありません。RDBMSのパラメータチューニングで調整できる範囲にも限界があります 注2。このような状況を防ぐために、データベースの設計においては「あらかじめ容量や処理量を計算しておくこと=キャパシティプランニング」が重要です。

また、データベースの成長を考えた場合、1台のサーバで収まらなければパーティショニング(シャーディング)を検討することになります。その際、どの程度のデータベースサイズで分割するのか、といった判断を行うためにも、キャパシティプランニングは必須の作業です。

キャパシティプランニングにおいてデータベースのサイズを見積もるには、基本的に次の手順を踏みます。


  1. テーブルの論理設計を行う(RDBMS非依存)
  2. 論理的なレコードの量を見積もる
  3. テーブル/インデックスの物理設計を行う(RDBMS製品依存)
  4. 各カラムのデータサイズなどを調べ、各テーブルの物理データ容量を見積もる
  5. 各テーブル/インデックスのデータサイズを合算してデータベース全体の容量を見積もる

これらを実施して、個別のテーブルの容量を算出したうえで、開発に入ったら「このSQLでは何件のレコードを抽出・処理しているのか」をきちんと認識しながら、SQLを作成する必要があります(詳細は後述)。

先に述べたように、「I/Oを制する者はデータベースを制す」であり、「データベースは生き物」です。よって、データの容量をきちんと見積もり、把握しておくことは、データベース開発における最優先事項なのです。

参考
注2:実際、1週間ほどかけてチューニングを試みた結果、アプリケーションが作りなおしになった事例もあります。

【べからず】 デフォルトのパラメータ設定のまま使ってはいけない

各データベース製品では、セットアップやデータベースの初期化を行った際に、設定ファイルにデフォルト値がセットされます。しかし、開発・運用を行う際、これらの初期設定をそのまま利用してはいけません。必ず設定を確認し、自身のデータベースに合わせて「パラメータ設計」をしておく必要があります。というのも、これらの設定ファイルの初期値は、必ずしも実際に稼働するデータベースのデータ容量やハードウェア環境を考慮した値になっているとは限らないためです。

たとえば、16GBの物理メモリを搭載したサーバでPostgreSQLの初期化コマンド(initdb)を実行すると、共有バッファのサイズの初期値は32MBとなり、ほかの設定値もかなり小さな値に設定されます。それに気付かず稼働させると、ハードウェアの持つポテンシャルを引き出せず、ハードウェアへの投資が無駄になってしまいます。

また、ログファイルの出力内容などを確認しておく必要もあります。ログの設定が不十分だったためにトラブルシューティングの際に必要な情報が出力されていない、ということが往々にして発生します。そのため、これらの設定内容を理解し、設計時にあらかじめ(ある程度)適切な値に設定しておく必要があります。たとえばPostgreSQLにおける必須の設定確認項目は表1のとおりです。

表1 PostgreSQLの必須設定確認項目
項目 説明(値の目安)
shared_buffers 共有バッファのサイズ(物理メモリの1/4~1/2)
checkpoint_segments チェックポイントの発生間隔(16~32)
wal_buffers トランザクションログバッファサイズ(64~128)
log_line_prefix サーバログの各行のプレフィックス
参考

次回は、開発編です。

(2011年6月24日 WEB+DB PRESS Vol.63 掲載)
(2011年11月14日 公開)