無料PHPプログラム

MySQL 5.1 リファレンスマニュアル :: 6 最適化 :: 6.2 SELECTステートメントおよびその他のクエリの最適化 :: 6.2.19 その他の最適化のヒント
« 6.2.18 DELETEステートメントの速度

6.3 ロック関連の問題 »
Section Navigation      [Toggle]
  • 6.2 SELECTステートメントおよびその他のクエリの最適化
  • 6.2.1 EXPLAINを使用して、クエリを最適化する
  • 6.2.2 クエリパフォーマンスの推定
  • 6.2.3 SELECTクエリの速度
  • 6.2.4 WHERE 節最適化
  • 6.2.5 Range 最適化
  • 6.2.6 インデックス結合最適化
  • 6.2.7 IS NULL最適化
  • 6.2.8 DISTINCT最適化
  • 6.2.9 LEFT JOINとRIGHT JOIN最適化
  • 6.2.10 入れ子結合最適化
  • 6.2.11 外側Join 単純化
  • 6.2.12 ORDER BY最適化
  • 6.2.13 GROUP BY最適化
  • 6.2.14 LIMITの最適化
  • 6.2.15 テーブルスキャンを避ける方法
  • 6.2.16 INSERTステートメントの速度
  • 6.2.17 UPDATEステートメントの速度
  • 6.2.18 DELETEステートメントの速度
  • 6.2.19 その他の最適化のヒント

6.2.19. その他の最適化のヒント

このセクションでは、クエリ処理高速化のためのヒントを挙げます。

  • 接続オーバヘッドを回避するには、データベースに対して永続的な接続を使用します。永続的な接続を使用せずにデータベースに対して多数の新規接続を実行する場合は、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 * FROM tbl_name
      WHERE hash_col=MD5(CONCAT(col1,col2))
      AND col1='constant' AND col2='constant';
    
  • 頻繁に変わるMyISAMテーブルでは、全ての可変長カラム(VARCHAR、BLOB、そしてTEXT)の使用を避けてください。たった1つの可変長カラムを含む場合でも、テーブルではダイナミック行フォーマットが使用されます。章?13. ストレージエンジンとテーブルタイプを参照してください。

  • 一般に、1 つのテーブルを複数のテーブルに分割することは、行が大きくなるだけで高速化の役には立ちません。行にアクセスする際の、最も大きなパフォーマンス要因は、レコードの最初のバイトを見つけるためのディスクシークです。データの検索後、ほとんどの新規ディスクでは、大多数のアプリケーションに十分な速度で行全体を読み取ることができます。テーブルの分割が実際に有効な状況は、固定長テーブルへの変更が可能な可変長MyISAMテーブルの場合か、テーブルのスキャンを非常に頻繁に必要としながらもほとんどのカラムに必要としない場合のみです。章?13. ストレージエンジンとテーブルタイプを参照してください。

  • 多数の行の情報から計算する頻度を非常に高くする必要がある場合(カウントの場合など)、新たなテーブルを導入し、リアルタイムでカウンタを更新するほうがはるかに適しています。以下のような更新は非常に高速にできます。

    UPDATE tbl_name SET count_col=count_col+1 WHERE key_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を使用しても何も消失はしない。

Copyright c 1997, 2010, Oracle and/or its affiliates. All rights reserved. Legal Notices
Top / Previous / Next / Up / Table of Contents
© 2010, Oracle Corporation and/or its affiliates

無料CGI PHPスクリプト | 新着情報スクリプト | 営業日カレンダー | PHPマニュアル | MySQLマニュアル | PEARマニュアル

Copyright (c) 2010 jmcodex.com All rights reserved.