このセクションでは、クエリ処理高速化のためのヒントを挙げます。
接続オーバヘッドを回避するには、データベースに対して永続的な接続を使用します。永続的な接続を使用せずにデータベースに対して多数の新規接続を実行する場合は、thread_cache_size
変数の値の変更が必要になることがあります。項6.5.2. 「サーバパラメータのチューニング」を参照してください。
常にすべてのクエリがテーブル内に作成したインデックスを実際に使用していることを確認します。MySQLでは、EXPLAIN
ステートメントでこれを実行できます。項6.2.1. 「EXPLAIN
を使用して、クエリを最適化する」を参照してください。
大量に更新された
MyISAM
テーブルに対して複雑な
SELECT
クエリを使用しないようにします。これで、読み手と書き手間の競合から生じるテーブルロックを回避します。
削除されたレコードがない
MyISAM
テーブルの場合は、別のクエリでそのテーブルからの読み取りが行われるのと同時に行を挿入できます。これがあなたにとって重要ならば、行削除の回避をおこなうテーブルの使用を検討します。また、大量の行削除後のOPTIMIZE
TABLE
の実行を検討します。項13.4. 「MyISAM
ストレージエンジン」を参照してください。
この動作は、concurrent_inserts
変数設定をとおして、変更されます。行が削除されたテーブル上であっても、新しい行を付加できます。(またその結果、同時に挿入することが可能です。)項6.3.3. 「同時挿入」を参照してください。
ARCHIVE
テーブルで生じるデータ圧縮問題を修復するのに、OPTIMIZE
TABLE
を使用できます。項13.10. 「ARCHIVE
ストレージエンジン」を参照してください。
通常
の順で行を読み取る場合は、expr1
、expr2
、
...ALTER
TABLE ... ORDER BY
を使用してください。テーブルが大幅に変更された後にこのオプションを使用すると、パフォーマンスを改善できます。
expr1
、expr2
、
...
他のカラムの情報を基にした 「ハッシュされた」カラムを導入することが役立つ場合があります。このカラムが短いもので、一意性がある場合は、多数のカラムに「大きな」インデックスを使用するより大幅に高速化できます。MySQLでは、追加カラムの使用が以下のように非常に容易です。
SELECT * FROMtbl_name
WHEREhash_col
=MD5(CONCAT(col1
,col2
)) ANDcol1
='constant
' ANDcol2
='constant
';
頻繁に変わるMyISAM
テーブルでは、全ての可変長カラム(VARCHAR
、BLOB
、そしてTEXT
)の使用を避けてください。たった1つの可変長カラムを含む場合でも、テーブルではダイナミック行フォーマットが使用されます。章 13. ストレージエンジンとテーブルタイプを参照してください。
一般に、1
つのテーブルを複数のテーブルに分割することは、行が大きくなるだけで高速化の役には立ちません。行にアクセスする際の、最も大きなパフォーマンス要因は、レコードの最初のバイトを見つけるためのディスクシークです。データの検索後、ほとんどの新規ディスクでは、大多数のアプリケーションに十分な速度で行全体を読み取ることができます。テーブルの分割が実際に有効な状況は、固定長テーブルへの変更が可能な可変長MyISAM
テーブルの場合か、テーブルのスキャンを非常に頻繁に必要としながらもほとんどのカラムに必要としない場合のみです。章 13. ストレージエンジンとテーブルタイプを参照してください。
多数の行の情報から計算する頻度を非常に高くする必要がある場合(カウントの場合など)、新たなテーブルを導入し、リアルタイムでカウンタを更新するほうがはるかに適しています。以下のような更新は非常に高速にできます。
UPDATEtbl_name
SETcount_col
=count_col
+1 WHEREkey_col
=constant
;
これは、MyISAM
のようにテーブルロック(複数リーダ/単一ライタ)のみの
MySQL
ストレージエンジンを使用する場合に、非常に重要です。また、このような場合は行ロックマネージャで必要な作業が少なくなるため、ほとんどのデータベースでパフォーマンスが改善されます。
大きなログテーブルから統計を収集する必要がある場合は、テーブル全体をスキャンするのではなく、サマリテーブルを使用します。サマリの管理は、「リアルタイム」で統計を実行する場合と比較して非常に高速になります。 何らかの変更がある(業務上の決定に応じて)場合は、ログから新規にサマリテーブルを再生成したほうが、実行アプリケーションの変更よりはるかに高速です。
可能であれば、レポートを「リアルタイム」か「集計」かのいずれかに分類するように推奨します。集計レポートに必要なデータは、サマリテーブルから生成され、サマリテーブルは実データから生成されます。
カラムにデフォルト値がある利点を生かします。挿入対象の値がデフォルト値と相違する場合のみ明示的に値を挿入します。これで、MySQL が要する解析作業が軽減され、挿入の速度が改善されます。
状況によっては、データをBLOB
にパックし、格納したほうが便利です。このような場合は、BLOB
へのパックおよびパック解除を行うコードをアプリケーションに追加する必要がありますが、あるステージにおける大量のアクセスを省略できることになります。これは、固定長テーブル構造に準拠しないデータがある場合に実用的です。
通常は、すべてのデータが冗長にならないようにする必要があります。(データベースセオリの第 3 正規化)。しかし、高速化を図る必要がある場合はデータなどの複製やサマリテーブルの作成をためらうべきではありません。
ストアドルーチンや UDF(ユーザ定義関数)はパフォーマンスの向上に役立つ手段です。詳しくは、章 17. ストアドプロシージャとファンクションおよび項25.3. 「Adding New Functions to MySQL」を参照してください。
アプリケーションのクエリと応答をキャッシュすること、および挿入と更新の同時実行を試行することは必ず高速化に役立ちます。データベースでロックテーブルがサポートされる場合(MySQL や Oracle など)は、これによって確実にすべての更新後にインデックスキャッシュが 1 回だけフラッシュされるようにできます。MySQLのクエリキャッシュも、同様の結果を得るために利用できます。詳しくは項4.13. 「MySQL クエリ キャッシュ」を参照してください。
データの書き込みするタイミングを知る必要がない場合はINSERT
DELAYED
を使用します。多数の行が 1
回のディスクへの書き込みで書き込まれるため、これで高速化が図れます。
SELECT
の優先を上げる場合は、INSERT
LOW_PRIORITY
を使用します。
キューをジャンプするようにする場合は、SELECT
HIGH_PRIORITY
を使用します。言い換えると、書き込み待機中のユーザがいる場合でも、SELECT
を実行できるようになる。
1 つの
SQLステートメントで多数の行を格納するには、複数行のINSERT
ステートメントを使用します。これは、MySQLを含む多数の
SQL でサポートされています。
大量のデータをロードする場合はLOAD
DATA
INFILE
を使用します。これは通常のINSERT
より高速になります。
一意の値にするには、AUTO_INCREMENT
カラムを使用します。
一定の間隔で OPTIMIZE TABLE
を使用して、動的MyISAM
テーブルの断片化を回避します。項13.4.3. 「MyISAM
テーブルストレージフォーマット」を参照してください。
さらに高速化が可能であれば、MEMORY
テーブルを使用します。詳しくは項13.7. 「MEMORY
(HEAP
)
ストレージエンジン」を参照してください。頻繁にアクセスされる非クリティカルデータ(クッキーなしでユーザに最後に表示されたバナーの情報など)にはMEMORY
テーブルを使用します。多くのWebアプリケーション環境では、
揮発性データの処理にユーザセッションも使用できます。
Webサーバでは、画像と他のバイナリアセットを通常ファイルとして格納します。言い換えると、データベース内にはファイル参照のみを格納します。この主な理由は、通常の Web サーバのほうがデータベースコンテンツと比較してファイルのキャッシュに優れているためです。このため、ファイルを使用したほうがシステムの高速化を容易に図れます。
別のテーブルで同一情報を扱うカラムは、同じ宣言をし、同じデータ型を持つようにします。この結果、一致カラムに基づく結合速度が速くなります。
カラム名はなるべく単純なものに保持します。たとえば、customer
テーブルではcustomer_name
ではなく name
を使用します。他の SQL
サーバに移植可能にすることを考慮するなら、名前を
18 文字未満にする。
高速化が大きく必要とされる場合は、複数の
SQL
サーバがサポートするデータストレージの低レベルインタフェースを調べる必要があります。たとえば、MySQL
MyISAM
ストレージエンジンに直接アクセスすることによって、SQL
インタフェース使用時と比較して 2~5
倍の速度が得られることもあります。
これを実行可能にするには、データをアプリケーションと同じサーバに配置し、また通常は
1
プロセスのみからアクセスするようにする必要があります(外部ファイルロックが非常に低速なため)。上記の問題は、MySQL
サーバに低レベルの MyISAM
コマンドを導入することで解消できます(必要に応じてパフォーマンスを改善する容易な手段の
1
つとなるのです)。データベースインタフェースを慎重に設計することで、この種の最適化を容易にサポートできる。
多くの場合、テキストファイルにアクセスするのと比較して、データベースからデータにアクセスしたほうが高速である。この理由は一般にテキストファイル(数値データ使用時)よりデータベースのほうがよりコンパクトで、必要なディスクアクセスが少ないことによる。また、テキストファイルを解析してレコードとカラムの境界を検索する必要がないため、コードも節約できる。
レプリケーションはオペレーションによって、性能向上を図ります。負荷を分散させるため、クライアント修正をレプリケーションサーバに分布できる。バックアップを作成する間マスタの速度が低下するのを避けるため、スレーブサーバを作成することができる。章 5. レプリケーションを参照してください。
DELAY_KEY_WRITE=1
オプションでMyISAM
テーブルを定義すると、ファイルが閉じられるまでディスクにログが記録されないためインデックス更新の速度が上がる。
この欠点は、途中で mysqld
の強制終了が発生した場合にテーブルに問題がないことを確認するため、mysqld
を開始する前に、テーブルに対して
myisamchkを実行するか、--myisam-recover
でサーバを作動させる必要があるということである。キー情報は常にデータから生成可能であるため、DELAY_KEY_WRITE
を使用しても何も消失はしない。