1

2 つのテーブルがあります。1 つには 50 のレコードがあり、いくつかの都市名が含まれており、もう 1 つのレコードには 3173958 のレコードがあり、都市から国へのコード情報が含まれています。

+---------+-----------+
| country | city      |
+---------+-----------+
| gb      | sapiston  |
| gb      | sapperton |
| gb      | sarclet   |
| gb      | sarnau    |
| gb      | sarnau    |
+---------+-----------+

大きなテーブルはフィールドにインデックスが作成されていcityますが、このクエリの実行には約5 分かかります。

SELECT small.* , c2c.country FROM small LEFT JOIN c2c ON ( lower( small.city ) = lower( c2c.city ) );

何が問題ですか?
どうすれば速くなりますか?

4

2 に答える 2

3

cityインデックスを利用するには、クエリで下位関数を適用してもインデックスを利用できないため、値を下位形式で同じ列または別のインデックス付き列に格納する必要があります。

SELECT small.* , c2c.country 
FROM small 
     LEFT JOIN c2c 
         ON small.city = c2c.city;

また、パフォーマンスを向上させるために、次のインデックスとカバリング インデックスをテーブルに追加します。

ALTER TABLE small ADD KEY ix1(city);
ALTER TABLE c2c ADD KEY ix1(city, country);

上記のインデックスを追加した後、EXPLAINを使用してクエリ実行プランを確認します

于 2012-09-10T09:08:08.257 に答える
2

WHERE 句内の列名に対して関数を使用する場合、インデックスは使用できません。MySQL は、比較を行う前にすべての行の計算値を取得する必要があるためです。等価比較では通常、大文字と小文字が区別されないため (列の照合順序によって異なります)、LOWER 関数を安全に省略できます。改訂されたクエリは次のとおりです。

SELECT small.*, c2c.country
FROM small
LEFT JOIN c2c ON small.city = c2c.city

次に、カバリング インデックスを に追加する必要がありますc2c。に索引を作成する必要があります(city, country)。このように、MySQL は国名を取得するためにテーブルを参照する必要がありません。結合中にインデックスを確認し、同時に同じインデックスから列をcityフェッチできます。country

次に、small.*必要な列のみに変更します。

次に、まだインデックスを作成しsmall.cityていない場合、またはsmallテーブルから 2 つまたは 3 つの列だけが必要であることがわかっている場合は、代わりにカバリング インデックスを作成します。たとえば、選択している場合small.somecolumn(およびsmall.cityWHERE/ON 句で使用している場合) のインデックスを作成します(city, somecolumn)

最後に、city両方のテーブルの列が同じデータ型、長さ、そして最も重要な照合順序であることを確認してください。照合が異なる場合、MySQL は比較する前に照合を変換する必要があり、クエリが遅くなる可能性があります。

于 2012-09-10T09:17:31.867 に答える