Оптимизировать время следующего запроса в sql
select *
from ((select 'Temp', r.*
from tab1 r
where (r.fa, r.date, r.status) not in (select r1.fa, r1.date, r1.status from tab2 r1)
) union all
(select 'report', r.*
from tab2 r
where (r.fa, r.date, r.status) not in (select r1.fa, r1.date, r1.status from tab1 r1)
)
) temp
order by fa;
По мере увеличения данных время запроса увеличивается. Пожалуйста, предоставьте решение для оптимизации времени, даже если данные продолжают увеличиваться
3 ответа
Поэтому вы хотите данные A + B -(пересечение B). Для этого вы используете 1 союз и 2 не в пункте. Я попытался устранить те в следующем запросе:
SELECT *
FROM(
SELECT X.*, COUNT(DISTINCT CN) OVER(PARTITION BY r.fa,r.date,r.status) CNT
FROM (
SELECT 'Temp' CN,r.*
FROM tab1 r
UNION ALL
SELECT 'report' CN,r.*
FROM tab2 r
)X)Y
WHERE Y.CNT=1
Сначала нужно выбрать все записи, используя UNION ALL вместо UNION. После этого отфильтруйте те записи, которые появились в обеих таблицах (tab1, tab2), для которых вы можете использовать аналитическую функцию.
Для вашего запроса вы должны начать с индексов:
tab1(r.fa, r.date, r.status)
tab2(r.fa, r.date, r.status)
Это должно ускорить not in
часть запросов. Существует не способ обойти order by
,
В общем, использование ненужного подзапроса влечет за собой дополнительные расходы. Тем не менее, потому что вы используете order by
подзапрос, вероятно, не имеет значения с точки зрения производительности.
WHERE (a,b) ...
никогда не был хорошо оптимизирован в MySQL. Избегайте конструкции.
IN ( SELECT ... )
только недавно был улучшен, но все же это не так хорошо, как EXISTS( SELECT * ...)
или же LEFT JOIN .. ON ..
, Переформулировать.
NOT IN
Плюс оба вышеперечисленных могут быть переформулированы в LEFT JOIN ... ON ... WHERE ... IS NULL
Вам не нужно внешнее SELECT
Вы можете сортировать UNION
таким образом:
( SELECT ... )
UNION ALL
( SELECT ... )
ORDER BY ... -- applies to UNION
Опционально SELECTs
также может иметь ORDER BY
, но это полезно только (?), если у вас есть LIMIT
,