3

ルート用と空港用の 2 つのテーブルがあります。

Routes には 9000 を超える行が含まれており、すべての列にインデックスを付けました。空港はわずか 2000 行で、すべての列にインデックスを付けました。

このクエリを実行すると、300 行を返すのに最大 35 秒かかる場合があります。

SELECT routes.* , a1.name as origin_name, a2.name as destination_name FROM routes
LEFT JOIN airports a1 ON a1.IATA = routes.origin
LEFT JOIN airports a2 ON a2.IATA = routes.destination
WHERE routes_build.carrier = "Carrier Name"

「DESCRIBE」で実行すると、次の情報が得られますが、それが何を言っているのか100%確信が持てません。

id | Select Type   | Table             | Type   | possible_keys        | Key            | Key_len   | ref    | rows     | Extra
--------------------------------------------------------------------------------------------------------------------------------------
1  | SIMPLE        | routes_build      | ref    | carrier,carrier_2    | carrier        | 678       | const  | 26       | Using where
--------------------------------------------------------------------------------------------------------------------------------------
1  | SIMPLE        | a1                | ALL    | NULL                 | NULL           | NULL      | NULL   | 5389     |
--------------------------------------------------------------------------------------------------------------------------------------
1  | SIMPLE        | a2                | ALL    | NULL                 | NULL           | NULL      | NULL   | 5389     |
--------------------------------------------------------------------------------------------------------------------------------------

私が考えることができる唯一の代替手段は、2 つの個別のクエリを実行し、それらを PHP で結合することですが、このようなものが mysql サーバーを停止させる可能性があるとは信じられません。いつものように、私は何か愚かなことをしていると思います。SQL は私の最大の弱点です。

4

5 に答える 5

3

個人的には、各ルートには始点と終点が必要なため、左側の結合を削除して内部の結合に置き換えることから始めます。

于 2009-06-26T15:34:25.113 に答える
1
SELECT  routes.*, a1.name as origin_name, a2.name as destination_name
FROM    routes_build
LEFT JOIN
        airports a1
ON      a1.IATA = routes_build.origin
LEFT JOIN
        airports a2
ON      a2.IATA = routes_build.destination
WHERE   routes_build.carrier = "Carrier Name"

あなたからEXPLAIN PLAN私はあなたがにインデックスを持っていないことがわかりますairports.IATA

クエリが高速に動作するように作成する必要があります。

コードは一意であるUNIQUEため、名前はインデックスであることも示唆しています。IATA

アップデート:

テーブル定義を投稿してください。次のクエリを発行して表示します。

SHOW CREATE TABLE airports

また、構成を以下に設定しない限り、FULLTEXTインデックスIATAは役に立たないことに注意してください。ft_max_word_lenMySQL3

デフォルトでは、です4

IATAコードは3文字の長さであり、デフォルト設定MySQLを使用してそのような短い単語を検索しません。FULLTEXT

于 2009-06-26T15:39:30.080 に答える
1

これは、空港テーブルへの参加にインデックスを使用していないことを示しています。「rows」列が非常に大きく、5000 桁もあるのがわかりますか? これは、クエリに答えるために読み取らなければならない行数です。

すべての列にインデックスを付けたと主張しているように、理由はわかりません。IATAとは?ユニークですか?mysql がインデックスが非効率的であると判断した場合、それは無視される可能性があると思います。

編集: IATA が一意の文字列の場合、その半分だけをインデックスに登録してみませんか? (インデックスを作成する文字数を選択できます) これにより、mysql が使用できるインデックスが得られる場合があります。

于 2009-06-26T15:43:31.633 に答える
0

LEFTMartin Robins の優れたアドバイス (つまり、クエリから単語のすべてのインスタンスを削除する) を実装した後、 、、およびroutes_buildに複合インデックスを与えてみてください。carrierorigindestination

于 2009-06-26T15:38:15.420 に答える
0

それは本当にあなたが取得しようとしている情報に依存します。おそらく、エアポートに 2 回参加する必要はなく、おそらく左結合を使用する必要もありません。また、テキスト フィールドではなく数値フィールドで検索できる場合は、速度も向上します。

それで、あなたは何を取得しようとしていますか?

于 2009-06-26T15:39:17.100 に答える