2014-01-31 2 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

Извините за это безобразие, я не знал, как форматировать это в Вот. и m в срочной необходимости. –

ответ

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 для JOINS и что хороший переформатирование :) – 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 вы проверяете для ids, которые NOT в некотором результате, так что это не имеет значения, если в этом результате некоторые ids более одного раза.

+0

Спасибо, сэр, первая отличительная черта была моей ошибкой, но я оставил два, которые я сделал, чтобы уменьшить размер подзапроса и быстрее сделать оператор IN, но не уверен, был ли я прав в этом или нет. –

Смежные вопросы