2

geonames.orgの地理空間データベースを使用しています。現在、検索語をデータベースに転送して適切な結果を返すオートコンプリート入力フィールドをウェブサイトに持っています。重要なことの 1 つは、結果を国別に並べ替える必要があることです。

私が選択したテーブルは約 900.000 行あり、次のように作成されます。

CREATE TABLE IF NOT EXISTS `geonames` (
`id` integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
`country_code` char(2) NOT NULL,
`postal_code` varchar(20) NOT NULL,
`place_name` varchar(180) NOT NULL,
...
FULLTEXT(country_code),
FULLTEXT(postal_code),
FULLTEXT(place_name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

典型的なステートメントは次のようになります。

SELECT postal_code, place_name FROM geonames WHERE LOWER(`place_name`)
LIKE 'washin%' ORDER BY FIELD (country_code, 'JE', 'GB', 'FR', 'LI', 'CH',
'DK', 'LU', 'BE', 'NL', ... many more countries in that list ... ) DESC;

部分を高速化するためにFULLTEXTインデックスを使用しWHERE place_name LIKE 'washin%'ます。しかし、それでもクエリはやや遅いです。SQL クエリのタスクは、place_name一致するテーブル内のすべてを検索し'washin%'、指定された国に従って結果を並べ替えることです。一度に大量のデータが要求されるため、クエリが遅くなりますか? はいの場合、このボトルネックで実行時間を短縮するにはどうすればよいですか?

私は決してMySQLの専門家ではないので、より経験豊富な人が表示されたSQLクエリを高速化するのを手伝ってくれるか、少なくとも最適化の方向性を教えてくれたらうれしいです.

どうもありがとうございました!

4

2 に答える 2

4

LOWERインデックスを効率的に使用できないため、 where 句では避ける必要があります。

SELECT postal_code, place_name FROM geonames
WHERE `place_name` LIKE 'washin%'
ORDER BY FIELD(country_code, 'JE', 'GB',  ...) DESC;

代わりに、大文字と小文字を区別しない照合を使用する必要があります。で終わる照合で_ciは、大文字と小文字が区別されません。大文字と小文字を区別する照合は で終わり_csます。

また、全文索引は、を使用したクエリには役立ちませLIKEで B-TREE インデックスを使用する必要がありますplace_name

B ツリー インデックスの特徴

B ツリー インデックスは、=、>、>=、<、<=、または BETWEEN 演算子を使用する式の列比較に使用できます。LIKE の引数がワイルドカード文字で始まらない定数文字列である場合、インデックスは LIKE 比較にも使用できます。

また、インデックスにcountry_codeandを含めることもできます(ただし、最初の列としてではありません)。postal_codeこれにより、クエリのカバリング インデックスが得られます。

またORDER BY、呼び出しのためにインデックスを効率的に使用することはできませんが、FIELD返される結果の数が比較的少ない場合は問題になりません。

于 2012-12-22T21:48:32.317 に答える
0

LOWER関数の呼び出しを削除します。mysql ではLIKE大文字と小文字を区別しないため、呼び出す必要はありません。

于 2012-12-22T22:22:01.143 に答える