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