#sql #sql-server #tsql #sqlperformance
#sql #sql-server #tsql #производительность SQL
Вопрос:
Я надеюсь, что кто-нибудь здесь сможет мне помочь. Мне был предоставлен этот запрос, выполнение которого занимает много времени (более 30 минут). Я пытался переписать запрос, но пока безуспешно. Я публикую пример запроса, чтобы вы могли получить представление о том, что я пытаюсь сделать.
В таблице 1 2000 записей. Table2 содержит 2000000 записей.
Table2 может не содержать запись, которую он пытается найти. Поэтому нельзя использовать ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ или ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Я думаю, что это можно решить с помощью LEFT JOIN, но я не смог найти способ переписать его.
SELECT
ID, A, B,
CASE WHEN c IS NULL then
(SELECT max(distinct c) FROM TABLE2 tbl2 WHERE tbl1.Id = tbl2.Id)
ELSE
C
END as C,
CASE WHEN d IS NULL then
(SELECT max(distinct d) FROM TABLE2 tbl2 WHERE tbl1.Id = tbl2.Id)
ELSE
D
END as D,
CASE WHEN e IS NULL then
(SELECT max(distinct e) FROM TABLE2 tbl2 WHERE tbl1.Id = tbl2.Id)
ELSE
e
END as e,
f, g, h, i
FROM TABLE1 tbl1
Вместо того, чтобы запускать запрос ‘select max’ 3 раза, есть ли способ объединить таблицу только один раз, чтобы «один и тот же» запрос не выполнялся 3 раза? Причиной максимального значения является то, что Table2 может содержать несколько записей с одинаковым идентификатором. В этом случае считайте Id как Order_Id с номерами нескольких строк заказа.
Надеюсь, это имеет смысл.
Комментарии:
1.
OUTER APPLY
казалось бы, это то, что вы хотите. Хотя ничто не указывает на то, что это является причиной ваших проблем с производительностью. На самом деле вам нужно изучить план выполнения и определить, где используется время.2. Попробуйте включить индекс
table2 (id ASC, e DESC)
.3. Пожалуйста, поделитесь планом запроса через brentozar.com/pastetheplan . Мы не сможем помочь вам должным образом без этого
4. Не могли бы вы опубликовать определения таблиц?
5. используйте
index
и проверяйтеexecution plan
реакцию
Ответ №1:
Казалось бы, ваш запрос должен сводиться к следующему, работает ли это для вас и работает ли лучше?
select
t1.ID, t1.A, t1.B,
IsNull(t1.c, t2.c) C,
IsNull(t1.d, t2.d) D,
IsNull(t1.e, t2.e) E,
t1.f, t1.g, t1.h, t1.i
from TABLE1 t1
outer apply (
select Max(c) c, Max(d) d, Max(e) e
from TABLE2 t2
where t2.Id = t1.Id
)t2
Комментарии:
1. Потрясающе! Похоже, это помогает. И теперь запрос занимает 33 секунды. Мне все еще нужно убедиться, что значения правильные, но это выглядит правильно и тааак намного быстрее.
2. Все еще занимает 10 минут, но это намного лучше, чем 30 минут до этого. Далее, я думаю, я начну изучать план выполнения и посмотрю, где теряется время. Я добавил индекс в таблицу 2, но выполнение простого «ВЫБРАТЬ * ИЗ таблицы2» и получение его для отображения всех записей занимает чуть более 3 минут, так что проблема заключается в этом. В таблице 2 около 2 миллионов записей. Действительно ли отображение в SQL Server с некластеризованным индексом должно занимать 3 минуты?
3. Существует много причин и неизвестных, вам нужно будет задать конкретный вопрос о производительности и предоставить подробную информацию о таблицах, существующих индексах и, в конечном счете, плане выполнения.
4. Кроме того, он составляет 1/3 от продолжительности и попадает в вашу таблицу2 один раз вместо 3 раз, так что, по крайней мере, это имеет смысл.