0

「ORDERBY」に使用する列のインデックスを作成すると、MySQLクエリへの応答がはるかに速くなることに気付きました。

SELECT username FROM table ORDER BY registration_date DESC

ここで、リクエスト時間を最適化するためにどのインデックスを作成する必要があるのか​​疑問に思っています。たとえば、私は次のクエリを頻繁に使用します。

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
    && status='active'

SELECT username FROM table WHERE
    status='active'

SELECT username FROM table ORDER BY registration_date DESC

SELECT username FROM table WHERE
    registration_date > ".(time() - 10000)."
    && status='active'
    ORDER BY birth_date DESC

質問1: 最初の3つのリクエストタイプに個別のインデックスを設定する必要がありますか?(つまり、列「registration_date」の1つのインデックス、列「status」の1つのインデックス、および両方の組み合わせの別の列?)

質問2: 「WHERE」と「ORDERBY」には異なるインデックスが個別に使用されていますか?たとえば、「status」列と「registration_date」列の組み合わせインデックスと、「birth_date」列のみの別のインデックスがあるとします。3つの列(「status」、「registration_date」、「birth_date」)に別の結合インデックスを設定する必要がありますか?

4

5 に答える 5

3

インデックスやクエリの最適化に関する厳格なルールはありません。それぞれのケースを検討し、検討する必要があります。

ただし、一般的に言えば、WHEREステートメントで頻繁に並べ替えたり使用したりする列にインデックスを追加することができます。(質問2への回答-いいえ、同じインデックスがとに使用される可能性ORDER BYがありWHEREます)複数列のインデックスを実行するか、単一列のインデックスを実行するかは、クエリの頻度によって異なります。また、単一列のインデックスは、インデックスマージ最適化を使用してmySQLによって結合される可能性があることに注意してください。

Index Mergeメソッドは、複数の範囲スキャンで行を取得し、それらの結果を1つにマージするために使用されます。マージにより、基になるスキャンの和集合、交差、または交差の和集合が生成される可能性があります。このアクセス方法は、単一のテーブルからのインデックススキャンをマージします。複数のテーブルにまたがるスキャンをマージしません。

(詳細:http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html

複数列のインデックスでは、インデックス付きの列の使用がインデックスの列の順序と一致するようにクエリを構造化するように注意する必要もあります。

列がインデックスの左端のプレフィックスを形成していない場合、MySQLはインデックスを使用できません。ここに示されているSELECTステートメントがあるとします。

SELECT * FROM tbl_name WHERE col1 = val1; SELECT * FROM tbl_name WHERE col1 = val1 AND col2 = val2;

SELECT * FROM tbl_name WHERE col2 = val2; SELECT * FROM tbl_name WHERE col2 = val2 AND col3 = val3;

(col1、col2、col3)にインデックスが存在する場合、最初の2つのクエリのみがインデックスを使用します。3番目と4番目のクエリにはインデックス付きの列が含まれますが、(col2)と(col2、col3)は(col1、col2、col3)の左端のプレフィックスではありません。

インデックスには独自のパフォーマンスの考慮事項があることに注意してください。テーブルを「オーバーインデックス」する可能性があります。レコードが挿入されるか、インデックス付きの列が変更されるたびに、インデックス/インデックスを再構築する必要があります。これにはリソースが必要であり、テーブルのサイズと構造によっては、インデックス作成操作がアクティブなときに応答性が低下する可能性があります。

EXPLAINクエリで何が起こっているかを正確に調べるために使用します。分析し、実験し、やりすぎないでください。ショットガンアプローチは、データベースの最適化には適していません。

ドキュメンテーション

于 2012-07-27T15:34:10.267 に答える
1

このページを引用するには:

[インデックス]は更新と挿入を遅くします。

それはあなたが計算しなければならないトレードオフです。テーブルを最適化するには、条件を適用する可能性が最も高い列にのみインデックスを配置する必要があります。インデックスが多いほど、データ変更操作が遅くなります。その意味で、私は個人的に、結合されたインデックスを作成することにあまりメリットはありません-3列のインデックスの7つの可能な順列すべてを作成する場合、3列の3つのインデックスを使用するよりも、更新と挿入により多くのドラッグをかけることになります。 (そしてそれでさえ議論の余地があるかもしれません)。一方、データが編集されているよりもはるかに少なく編集されている場合SELECT、インデックスは本当にスピードアップに役立ちます。

考慮すべき他の何か(再び上記のページを引用):

テーブルが非常に小さい場合[...]インデックスを除外してテーブルスキャンを実行させるよりも、インデックスを使用する方が悪いです。インデックスは、実際には、行数が多いテーブルでのみ役立ちます。

于 2012-07-27T15:30:40.977 に答える
1

はい、順序付けとwhere句の両方で、頻繁に使用する列にインデックスを付けることをお勧めします。

ただし、インデックスがある場合は、UPDATES、INSERTS、およびDELETEの速度が低下することに注意してください。

これは、このような操作の後、インデックスも更新する必要があるためです。

したがって、経験則として、アプリケーションが読み取りを集中的に使用する場合は、役立つと思われるインデックスを使用してください。

アプリケーションが頻繁にデータを更新している場合は、インデックスが原因でデータが遅くなる可能性があるため、注意してください。

疑わしいときは、単に手を汚して、EXPLAINの結果を調べなければなりません。

http://dev.mysql.com/doc/refman/5.6/en/explain.html

于 2012-07-27T15:30:41.613 に答える
1

最初の2つの例については、{registration_date、status}という1つのインデックスで満たすことができます。このようなインデックスは、最初のアイテム(registration_date)または両方のフィルターをサポートできます。

ただし、ステータスだけでは機能しません。ステータスに関する問題は、ステータスがどの程度選択的であるかです。つまり、レコードのどの割合がステータス=「アクティブ」であるかを示します。これが高い割合である場合(つまり、平均して、すべてのデータベースページにアクティブなレコードがある場合)、インデックスはあまり役に立たない可能性があります。

による順序は注意が必要です。mysqlがこの目的でインデックスを使用するかどうかはわかりません。多くの場合、レコード全体を並べ替えるためにインデックスを使用することは、単にレコードを並べ替えるよりも効率的ではありません。インデックスを使用すると、ページ内のレコードへのランダムアクセスパターンが発生し、ページキャッシュよりも大きいテーブルで大きなパフォーマンスの問題が発生する可能性があります。

于 2012-07-27T15:31:08.057 に答える
0

selectステートメントのexplain関数を使用して、結合の速度が低下している場所を特定します(参照される行が多いほど、速度が低下します)。次に、それらの列にインデックスを適用します。

EXPLAIN SELECT * FROM table JOIN table 2 ON a = b WHERE conditions;
于 2012-07-27T15:24:40.883 に答える