4

スロークエリログに表示されるクエリにインデックスを追加することで、ハンマーで打たれたワードプレス DB のパフォーマンスを改善しようとしています。

MS SQL では、クエリ ヒントを使用して、クエリでインデックスを使用するように強制できますが、通常、列を正しくカバーしていれば、クエリでインデックスを使用するのは非常に簡単です。

スロークエリログに頻繁に表示されるこのクエリがあります

SELECT SQL_CALC_FOUND_ROWS  wp_posts.ID 
FROM wp_posts  
WHERE 1=1  
  AND wp_posts.post_type = 'post' 
  AND (wp_posts.post_status = 'publish')  
ORDER BY wp_posts.post_date DESC 
  LIMIT 18310, 5;

MySQLでカバーする一意のインデックスを作成しwp_postspost_date, post_status, post_type and post_id再起動しましたが、Explain を実行すると、使用されるインデックスは

status_password_id

可能なキーでは、新しいインデックスは表示されませんが、それはカバーインデックスです。たとえば、取得するだけです

type_status_date,status_password_id

したがって、使用されるインデックスも、MySQL にオプティマイザーがある場合の可能な選択肢も、最初の列として post_date を持つインデックスを考慮していません。基本的にTOPを実行し、日付で並べ替えるクエリを考えていたでしょう

ORDER BY wp_posts.post_date DESC LIMIT 18310, 5;

速度を上げるために日付でソートされたインデックス、特にクエリを満たすために必要な他のすべてのフィールドを含むインデックスを使用したいと思いませんか?

MySQL には、インデックスを速度/パフォーマンス テストに強制的に使用するためのクエリ ヒントがありますか、それとも、このインデックスが無視されている理由を確認するために他に何かする必要がありますか?

Navicat に MS SQL のような Visual Query Execution Plan があればいいのですが、EXPLAIN が最高のようです。

インデックスを強制的に使用する方法、またはインデックスが無視される理由を解明する方法についてのヒントがある人は誰でも非常に役立ちます!

ありがとう

4

4 に答える 4

12

MySQL には、インデックスを速度/パフォーマンス テストに強制的に使用するためのクエリ ヒントがありますか、それとも、このインデックスが無視されている理由を確認するために他に何かする必要がありますか?

ドキュメントは、この質問にある程度詳しく答えています。

を指定するUSE INDEX(index_list)と、名前付きインデックスの 1 つだけを使用してテーブル内の行を検索するように MySQL に指示できます。代替構文IGNORE INDEX(index_list)を使用して、MySQL に特定のインデックスを使用しないように指示できます。これらのヒントはEXPLAIN、MySQL が可能なインデックスのリストから間違ったインデックスを使用していることを示している場合に役立ちます。

を使用することもできますがFORCE INDEX、これは のように機能USE INDEX(index_list) しますが、テーブル スキャンは非常に高価であると想定されます。つまり、テーブル スキャンは、特定のインデックスのいずれかを使用してテーブル内の行を検索する方法がない場合にのみ使用されます。

各ヒントには、列の名前ではなく、インデックスの名前が必要です。の名前はPRIMARY KEYですPRIMARY。テーブルのインデックス名を表示するには、 を使用しますSHOW INDEX

USE INDEXうまくいかない場合は、 を使用して、オプティマイザの 2 番目の選択 (または 3 番目など) を確認してみてくださいIGNORE INDEX

構文の簡単な例は次のとおりです。

SELECT * FROM t1 USE INDEX (i1) IGNORE INDEX (i2) WHERE ...

リンクされたドキュメントには、それがどこから来たのかがもっとたくさんあります。バージョン 5.0 のページにリンクしましたが、左側のサイドバーを使用して適切なバージョンに簡単に移動できます。バージョン 5.1 では、いくつかの追加の構文オプションが利用可能です。

于 2013-07-02T21:46:05.010 に答える
6

MySQL 5.6 は、 MySQL Workbench GUI がより魅力的な方法で視覚化できる新しい形式の EXPLAIN をサポートしています。しかし、MySQL 5.5 以前で立ち往生している場合、それは役に立ちません。

@AirThomasが言及しているように、MySQLにはヒントがありますが、実際には控えめに使用する必要があります。あなたが示すような単純なクエリでは、正しいインデックスがあれば、インデックス ヒントを使用する必要はありません。また、インデックス ヒントを使用すると、アプリケーションにインデックス名がハードコーディングされていることを意味するため、インデックスを追加または削除する場合は、コードを更新する必要があります。

クエリでは、インデックス(post_date, post_status, post_type, post_id)は役に立ちません。

インデックスの一番左の列を行制限に使用したい。だからpost_status, post_type最初に置く。より選択的な列が最初にある場合に最適です。つまりpost_type = 'post'、テーブルの 3% と一致し、テーブルのpost_status = 'publish'1% と一致する場合、post_type の前に post_status を最初に置きます。

=条件と演算子の両方に使用したためAND、一致するすべての行は基本的にこれらの 2 つの列に関連付けられていることがわかります。したがってpost_date、インデックスの 3 番目の列として使用すると、オプティマイザは、インデックスに格納されている順序で行をフェッチできることを認識し、ORDER BY の他の作業をスキップできます。EXPLAIN 出力から「Using filesort」が消えると、これが機能していることがわかります。

したがって、インデックスは次のようになります。

ALTER TABLE wp_posts ADD INDEX (post_status, post_type, post_date);

私のプレゼンテーションHow to Design Indexes, Reallyもお楽しみください。

この場合、InnoDB インデックスには主キー列が自動的に含まれるため、インデックスに ID を追加する必要はありません。

LIMIT 18310, 5コストがかかるに違いありません。MySQL は、サーバー側で最大 18315 行の結果セット全体を生成する必要がありますが、それらのほとんどを破棄するだけです。とにかく、世界で誰が 3662番目のページにスキップする必要がありますか?!

SQL_CALC_FOUND_ROWSページングしている大きな結果セットがある場合、MySQL は要求したページの前と後の両方で結果セット全体を生成する必要があるため、これは主要なパフォーマンス キラーです。本当に必要でない限り、そのクエリ修飾子を取り除くのが最善です.行数が必要な場合でも、. (* 両方の方法をテストして確認してください。)FOUND_ROWS()SELECT COUNT(*)

LIMIT の最適化に関するその他のヒントを次に示します。

于 2013-07-02T22:15:25.137 に答える