2014-01-31 18 views
0

我正在使用MySQL 5.0,並且需要對此查詢進行微調。任何人都可以告訴我,我能做些什麼調整?將NOT IN查詢轉換爲更好的性能

SELECT DISTINCT(alert_master_id) FROM alert_appln_header 
WHERE created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY) 
AND alert_master_id NOT IN (
SELECT DISTINCT(alert_master_id) FROM alert_details 
WHERE end_date IS NULL AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY) 
UNION 
SELECT DISTINCT(alert_master_id) FROM alert_sara_header 
WHERE sara_master_id IN 
(SELECT alert_sara_master_id FROM alert_sara_lines 
WHERE end_date IS NULL) AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY) 
) LIMIT 5000; 
+0

對不起,這醜陋,我不知道如何在這個格式這裏。而且急需。 –

回答

4

,我會做的第一件事是rewrite the subqueries as joins

SELECT  h.alert_master_id 

FROM  alert_appln_header h 

     JOIN schedule_config c 
     ON c.schedule_name = 'Purging_Config' 

    LEFT JOIN alert_details d 
     ON d.alert_master_id = h.alert_master_id 
     AND d.end_date IS NULL 
     AND d.created_date < CURRENT_DATE - INTERVAL c.parameters DAY 

    LEFT JOIN (
       alert_sara_header s 
     JOIN alert_sara_lines l 
      ON l.alert_sara_master_id = s.sara_master_id 
      ) 
     ON s.alert_master_id = h.alert_master_id 
     AND s.end_date IS NULL 
     AND s.created_date < CURRENT_DATE - INTERVAL c.parameters DAY 

WHERE  h.created_date < CURRENT_DATE - INTERVAL c.parameters DAY 
     AND d.alert_master_id IS NULL 
     AND s.alert_master_id IS NULL 

GROUP BY h.alert_master_id 

LIMIT  5000 

如果它還是後慢,重新審視你的索引策略。我建議在指標:

  • alert_appln_header(alert_master_id,created_date)
  • schedule_config(schedule_name)
  • alert_details(alert_master_id,end_date,created_date)
  • alert_sara_header(sara_master_id,alert_master_id,end_date,created_date)
  • alert_sara_lines(alert_sara_master_id)
+0

爲連接+1和那很好的重新格式化:) – GameDroids

1

好吧,這可能只是一個黑暗中的鏡頭,但我認爲你不需要這麼多DISTINCT這裏。

SELECT DISTINCT(alert_master_id) FROM alert_appln_header 
WHERE created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY) 
AND alert_master_id NOT IN (
    -- removed distinct here -- 
    SELECT alert_master_id FROM alert_details 
    WHERE end_date IS NULL AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY) 
    UNION 
    -- removed distinct here -- 
    SELECT alert_master_id FROM alert_sara_header 
    WHERE sara_master_id IN 
     (SELECT alert_sara_master_id FROM alert_sara_lines 
     WHERE end_date IS NULL) 
    AND created_date < DATE_SUB(CURDATE(), INTERVAL (SELECT parameters FROM schedule_config WHERE schedule_name = "Purging_Config") DAY) 
) LIMIT 5000; 

由於使用DISTINCT是非常昂貴的,請儘量避免它。在第WHERE條款您正在檢查idsNOT結果,因此結果某些ids出現不止一次應該沒有關係。

+0

謝謝主席先生,第一個不同的是我的錯誤,但其餘兩個我做的,以減少子查詢的大小,並使IN運算符更快,m不知道如果我在這裏是否正確。 –