私のクエリは現在約3秒かかりますが、これは最適化できると確信しています。私はそれを最適化する方法を理解することができません。
私のアプリにはかなり大きなproducts
テーブルがあります(約500,000レコード)。各製品は、50のドメインの1つにリストできます(表にリストされていdomains
ます)。製品とドメイン間のリンクは、domains_products
テーブル(約1,400,000レコード)に格納されます。遅いクエリは私のアプリの管理セクションにあり、どのドメインにもリストされていない製品を表示できるようにする必要があります。
関係のないすべての結合を削除して、必要最低限の要素を削除すると、問題のクエリは次のようになります。
SELECT `products`.*
FROM `products`
LEFT JOIN `domains_products`
ON `domains_products`.`product_id` = `products`.`id`
WHERE `products`.`deleted` = 'N'
AND `domains_products`.`domain_id` IS NULL
ORDER BY `products`.`id` ASC
このフォームでは、クエリに3秒以上かかり、3,000を少し超える商品が返されます(これは正しいです)。いずれかWHERE
の句を削除すると、クエリに0.12秒かかります(ただし、明らかに正しい結果が返されません)。
どちらのテーブルもInnoDBエンジンを使用しています。products
テーブルには、列に主キーがあり、列id
にインデックスがありdeleted
ます。domains_products
テーブルにはと列のみがあり、product_id
主domain_id
キーはこれらの両方の列にあり、両方に独自のインデックスがあります。関連するすべての列はNOT NULL
列です。
EXPLAIN
私にこれを与えます:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE products ref deleted deleted 1 const 188616 Using where
1 SIMPLE domains_products ref product_id product_id 4 products.id 1 Using where; Using index; Not exists
MySQLは正しいキーを検出しましたが、実際にはそれらを使用していないように見えることに注意してください。
プロファイラーはこれを言います:
Status Time
Starting 62 µs
Checking Permissions 7 µs
Checking Permissions 5 µs
Opening Tables 38 µs
System Lock 13 µs
Init 37 µs
Optimizing 17 µs
Statistics 1,3 ms
Preparing 25 µs
Executing 5 µs
Sorting Result 5 µs
Sending Data 3,3 s
End 28 µs
Query End 8 µs
Closing Tables 25 µs
Freeing Items 297 µs
Logging Slow Query 4 µs
Cleaning Up 5 µs
に掛かっているようですのでご注意くださいSending Data
。結合をNOTINに置き換えてみました:
SELECT `products`.*
FROM `products`
WHERE `products`.`deleted` = 'N'
AND `product`.`id` NOT IN (
SELECT `product_id`
FROM `domains_products`
)
ORDER BY `products`.`id` ASC
このクエリではまったく同じ結果が得られますが、3.8秒かかります。
このクエリを最適化するために、誰かが私を正しい方向に向けることができますか?