2017-05-11 16 views
0

私は内部結合を持つMySQLクエリを持っています.1つは結合を残し、データベースには多くのデータが残っていて、非常に遅いです。これは大体私のクエリです:MySQL LEFT JOIN ON条件の順

SELECT 
    main_table.* 
FROM 
    main_table 
INNER JOIN 
    ... 
LEFT JOIN 
    second_table ON (main_table.id = second_table.ref_id AND second_table.type = 'foo' AND second_table.bar IS NULL 
WHERE 
    second_table.id IS NULL 
; 

main_tableからエントリsecond_table内の1つの以上の参照のエントリを有することができます。 main_tableからすべての結果を取得したい場合は、結果がsecond_tableであるか、または第2のテーブル(type 'foo'またはbarがNULLである)には関係のないデータのみが含まれます。

をEXPLAIN に見ると、MySQLは最初ref_idをチェックするだけで、他の条件を確認するために非常に少数の結果を残してしまうのに対し、まだ、結果の何千につながること、type = 'foo'続く、bar IS NULL最初に検索。

私だけではないtypeまたはbarため、ref_idにインデックスを持っていると私はちょうど最初ref_idのクエリ検索を得ることができれば、私は、インデックスそれらに必要性を感じていません。

--edit:私はMySQLは他の上barを好む理由はおそらくですので(それが実際のデータを持ち、ゆっくりと走る)データベースのコピーに対して、typeと個別barにインデックスをも持っていないことに気づきましたキー。私は複数のフィールドにまたがるキーを検討しています。 -

誰もこの種のクエリを最適化する方法を知っていますか? ON条件で特定の順序でMySQLを強制することは可能ですか?


"解決策":関連するすべてのフィールドにインデックスを追加しました。

JOINがインデックス番号ref_idで最初に実行されたとすれば、これは本当の解決策ではないと私は信じています。それが唯一のインデックスだったときにはおそらくそうでしたが、私の同僚は何らかの理由で他のフィールドに別々にインデックスを追加する考えを持っていました。

+0

あなたができるとは思わない注文を保証できる場合でも、クエリを変更すると何が起こる可能性がありますか?その後、注文が再び変わる可能性があります。どこにでも役立つインデックスを追加するだけではいかがですか? –

+2

私は「wanna」という言葉で質問に答えません。それは単なるルールです。 – Strawberry

+0

私は今、 "どうしたいと思っているのか違いがありますか?")を検索しています) –

答えて

0

「無関係な」行をどこの部分に移動するとどうなりますか? は、DBはテーブルを結合簡単に時間を持っている必要があり、かつMYSQL JOINでは、インデックスに

SELECT 
    main_table.* 
FROM 
    main_table 
INNER JOIN 
    ... 
LEFT JOIN 
    second_table ON main_table.id = second_table.ref_id 
WHERE 
    second_table.id IS NULL OR 
    (second_table.type = 'foo' AND second_table.bar IS NULL) 
+0

これは私が最初に考えたものです。あなたのクエリは* 'type = 'foo''を含みますが、私は最終結果でそれらを除外する必要があります(私の' second_table.id IS NULL'をメモしてください)。条件に一致する2つ目のテーブルに一致するものが1つだけある場合は、主な結果を除外します。 – Simon

+0

main_tableの行に関連する行が1行あり、関係のない行が1行ある場合、その行は結果には表示されませんが、クエリには含まれます。右? –

+0

それはまさにそれです。 – Simon

0

よう

何かを使用するように思えることは速くLEFT JOINそのようにあなたは、このようなあなたのクエリを書くことができます。

SELECT 
    main_table.* 
FROM 
    main_table 
INNER JOIN 
    ... 
LEFT JOIN (SELECT main_table.*,second_table.* FROM main_table 

JOIN second_table ON main_table.id = second_table.ref_id AND 

second_table.type = 'foo' AND second_table.bar IS NULL) AS main_table2 ON 

main_table2.id = main_table.id 

WHERE 
second_table.id IS NULL;