我的查詢目前大約需要3秒,我敢肯定可以優化。我無法弄清楚如何優化它。需要幫助優化MySQL查詢與「不在」加入
我的應用程序有一個合理的大products
表(大約500,000條記錄)。每個產品可以列在50個域中的一個上(列在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秒,超過3000種產品將返回一點(這是正確的)。如果我刪除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
。我嘗試用NOT IN替換連接:
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秒。
任何人都可以指向正確的方向來優化此查詢嗎?
Re:「請注意,雖然MySQL已經發現了正確的密鑰,但實際上並沒有使用它們」:你說的是什麼? – ruakh
您是否刪除了大部分表格或進行了其他大型編輯?也許一個['OPTIMIZE TABLE'](http://dev.mysql.com/doc/refman/5.1/en/optimize-table.html)可以解決這個問題。 –
@ruakh我不是閱讀EXPLAIN語法的專家,但是因爲它在Extra-column中說「使用where」,所以我假設MySQL沒有使用索引。如我錯了請糾正我。 – rickdenhaan