3

名前と別のフィールドで検索するMySQL(ストアドプロシージャで使用)のクエリがあります。これらの検索パラメーターのさまざまな組み合わせを使用すると、迅速な結果(1〜2秒)が得られますが、特定の値を使用すると、本番Webサイトで結果を返すのに9秒かかるクエリが得られます。以下は、EXPLAINステートメントから得たものです。

id, select_type, table, type, possible_keys, key,       key_len, ref,   rows, Extra
--------------------------------------------
1,  SIMPLE,      Names, ref,  IX_Name,       IX_Name,   17,      const, 3173, Using where

名前はvarchar(40)として宣言され、他のフィールドはUnsigned smallint(6)です。クエリで使用されている名前(IX_Name)の最初の15文字にインデックスを使用しています。遅いクエリでは、EXPLAIN出力の「rows」列でチェックするために非常に多くの行が取得されることがわかります。

パフォーマンスを向上させるために何ができるかわかりません。上記のEXPLAIN出力に目立った問題はありますか?

ありがとう、ティム

4

4 に答える 4

3

どのようにテーブルにデータを入力しましたか?インデックスはツリー構造であり、効率的に機能するには、バランスを取る必要があります。これは、テーブルがバッチで読み込まれるか、定期的なメンテナンスが適用されると自動的に行われます。これらのどちらも当てはまらない場合、過度に成長したツリーの部分のインデックスの効率は大幅に低下します。

最も簡単なチェックは、インデックスを削除して再作成することです。後で同じ動作をする場合、それは別のことですが、少なくとも1つの可能性が排除されます。

于 2009-08-15T09:11:39.757 に答える
2

クエリが 1 つのフィールドのインデックスのみを使用しているようです。名前と「別のフィールド」で検索するとおっしゃいました。MySQL (特定の状況でのごく最近のバージョンを除く) は、クエリ内のテーブルオカレンスごとに 1 つのインデックスに制限されています。これは、名前にインデックスがあり、他のフィールドにインデックスがある場合、MySQL はどのインデックスが最も役立つかを推測し、他のものを無視する必要があることを意味します。より良いクエリ構造またはインデックス定義が役立つようです。あなたの名前が非常にユニークで、Explain Plan で 3,000 行を取得している場合、DB のメタデータが適切ではないか、他のフィールドに他の可能性がたくさんあります。

テーブルのクエリとスキーマを投稿できますか?

同じ SQL に対して、クエリは常に高速ですか、それとも低速ですか? つまり、Fisher を検索すると、高速な場合もあれば低速な場合もあり、一貫性がある場合もあります。それらが一貫している場合、CPU またはディスクのアクティビティが原因である可能性があります。変数の場合、DB 上の他のクエリが原因である可能性があります。

また、選択内容によっては、完全な結果をインデックスに入れることができれば、レコードを検証するためにディスクにヒットする必要がないため、クエリが実行されます。「インデックスを使用する」クエリでかなり驚くべき改善がありました。

ジェイコブ

于 2009-08-16T05:12:28.603 に答える
1

さて、プレフィックスにインデックスがあります。最初の 15 文字を使用しますが、使用したのは 1 文字だけで、テーブルの名前には次の値が含まれているとしましょう。

アル・バーブ ベス ベッシー ビル・ビフ ボブ・ボニー バック・バッド・カール

私のインデックスは最初の文字にのみあるため、データベースはインデックスが返すすべての行を読み取り、各名前全体を述語と比較する必要があります。

ここで「Al」を探すと、インデックスは 1 行返されます。次に、述語の 'Al' を行の 'Al' と比較し、一致したので、その行を返し、完了です。

ここで「Alex」を探すと、インデックスは 1 行返されます。次に、述語の 'Alex' を行の 'Al' と比較しますが、一致するものはなく、一致する可能性もありません。これで完了です。

しかし、'Bud' (または 'B' で始まるもの) を探すと、私のインデックスは 9 行を返します。完了する前に、9 行を読み取り、述語と比較する必要があります。

これを行う:

select substring( name, 1, 15), count(*)
from names
group by substring( name, 1, 15);

クイック ルックアップはユニークであることがわかると思いますが、低速ルックアップは多くの名前が共通のプレフィックスを共有する場所です。

于 2009-08-15T09:42:08.573 に答える
0

ユーザーにレンダリングしたい場合、3173行をかなり大きな数と見なすことができます。取得される実際のレコード数が大幅に少ない場合は、より多くのインデックスを作成することを検討する必要があります。EXPLAINが別の検索用語について何を報告するかを知っておくと便利です。

于 2009-08-15T15:00:45.773 に答える