私はかなり長い間、mySQL 5.0.51a のこの問題について頭を悩ませてきました。
LEFT JOIN を使用してテーブルを結合し、結合されたテーブルの列を WHERE 句で使用すると、mySQL は結合されたテーブルのプライマリ インデックスを JOIN で使用できず、FORCE INDEX (PRIMARY) も失敗します。
- 結合されたテーブルの列が WHERE 句にない場合、すべて正常に機能します。
- GROUP BY を削除すると、インデックスも使用されます。
それでも、私はそれらの両方が必要です。
障害:(私の特別なケースでは、最大1000秒の実行時間)
SELECT *
FROM tbl_contract co
LEFT JOIN tbl_customer cu ON cu.customer_id = co.customer_id
WHERE cu.marketing_allowed = 1 AND co.marketing_allowed = 1
GROUP BY cu.id
ORDER BY cu.name ASC
働いているが、私の問題を解決していない:
SELECT *
FROM tbl_contract co
LEFT JOIN tbl_customer cu ON cu.customer_id = co.customer_id
GROUP BY co.id
テーブル構造 (実際のテーブルはより複雑であるため、転記)
tbl_contract:
id: INT(11) PRIMARY
customer_id: INT(11)
marketing_allowed: TINYINT(1)
tbl_customer:
customer_id: INT(11) PRIMARY
marketing_allowed: TINYINT(1)
mySQL EXPLAIN は、参加時に可能なキーとして PRIMARY を認識しますが、使用しません。
1つの解決策がありました:
SELECT (...)
HAVING cu.marketing_allowed = 1
問題を解決しますが、ステートメント全体で 1 つの列しか選択できない他のコンテキストでクエリを使用しますが、HAVING は SELECT ステートメントで選択するためにmarket_allowed列を必要とします。
また、目的のテーブルで ANALYZE TABLE を実行すると、ローカル システムで mySQL 5.5.8 が正しく実行されることにも気付きましたが、ステートメントの直前に ANALYZE が実行されていることを常に保証できるとは限りません。とにかく、このソリューションは、本番サーバーの mySQL 5.0.51a では機能しません。:(
私が気付かなかったmySQLに特別なルールはありますか? 列が WHERE 句にある場合、LEFT JOIN インデックスが使用されないのはなぜですか? なぜ強制できないのですか?
事前にthx、
レネ
[編集]
いくつかの返信のおかげで、INNER JOIN を使用してクエリを最適化できましたが、残念ながら、完全に問題ないように見えますが、mySQL は ORDER BY 句を使用するときにインデックスの使用を拒否することがわかりました。
SELECT *
FROM tbl_contract co
INNER JOIN tbl_customer cu ON cu.customer_id = co.customer_id AND cu.marketing_allowed = 1
WHERE cu.marketing_allowed = 1
ORDER BY cu.name ASC
ORDER BY を省略した場合、mySQL はインデックスを正しく使用します。この例では関係がないため、GROUP BY を削除しました。
[編集2]
FORCING Indexes も役に立ちません。したがって、質問は次のとおりです。なぜ mySQL は結合にインデックスを使用しないのですか? これは通常、参加には影響しません...