簡體   English   中英

如何防止此JOIN查詢執行幾乎全表掃描

[英]How to prevent this JOIN query from doing an almost full table scan

項目中的數據集包含約440萬行

在每個表上分別對updatedcreated的索引編制索引

EXPLAIN SELECT i.id, j.id 
    FROM jobs j 
JOIN items i ON j.items_id = i.id 
WHERE j.updated > DATE_SUB(NOW(), INTERVAL 60 MINUTE) 
    OR j.created > DATE_SUB(NOW(), INTERVAL 60 MINUTE) 
    OR i.updated > DATE_SUB(NOW(), INTERVAL 60 MINUTE);

這是我得到的:

1   SIMPLE  i   index   PRIMARY,updated_idx                     updated_idx       5     NULL            4168353    Using index
1   SIMPLE  j   ref     items_id_idx,updated_idx,created_idx    items_id_idx      9      my_db.i.id     1          Using where

如您所見,在使用updated_idx ,這些項目仍然接近全表掃描。

為什么會這樣,無論如何我都可以避免這種情況?

也嘗試過此方法,但性能較差:

EXPLAIN SELECT i.id, j.id 
    FROM jobs j 
WHERE j.updated > DATE_SUB(NOW(), INTERVAL 60 MINUTE)
    OR j.created > DATE_SUB(NOW(), INTERVAL 60 MINUTE) 
    OR j.items_id IN 
         (SELECT i.id FROM items i WHERE i.updated > DATE_SUB(NOW(), INTERVAL 60 MINUTE));

MySql沒有優化或在where條件中設置的條件太好。 將查詢重寫為3個單獨的選擇,並與並集相連。 這樣,每個查詢都可以利用適當的索引:

SELECT i.id, j.id 
    FROM jobs j 
JOIN items i ON j.items_id = i.id 
WHERE j.updated > DATE_SUB(NOW(), INTERVAL 60 MINUTE)
UNION DISTINCT  
SELECT i.id, j.id 
    FROM jobs j 
JOIN items i ON j.items_id = i.id 
WHERE j.created > DATE_SUB(NOW(), INTERVAL 60 MINUTE) 
UNION DISTINCT
SELECT i.id, j.id 
    FROM jobs j 
JOIN items i ON j.items_id = i.id 
WHERE i.updated > DATE_SUB(NOW(), INTERVAL 60 MINUTE);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM