Member 11706445 Ответов: 3

Длительное выполнение join в sql server занимает много времени


Всем Привет,

Приведенный ниже запрос занимает много времени при выполнении, то есть почти до 2 часов, а иногда и больше. Таблицы LAR_PRODUCTS и STORE_RANGE_GRP_MATCH являются физическими таблицами и содержат количество записей 432837 и 103038 соответственно. Любое предложение сократить время выполнения запроса приветствуется.

Select 1                                  
      From LAR_PRODUCTS prd    with (nolock)                              
      Join STORE_RANGE_GRP_MATCH srg with (nolock)                                 
      On  prd.Store_Range_Grp_Id = srg.Orig_Store_Range_Grp_ID                                  
      And  srg.Match_Flag  = 'Y'                                  
      And  prd.Range_Event_Id = srg.LAR_Range_Event_Id                                  
                                  
      Where srg.Range_Event_Id Not IN (Select Range_Event_Id                                  
           From Last_Authorised_Range



Что я уже пробовал:

Я пробовал использовать indexed для обеих таблиц, но все равно это занимает много времени

PIEBALDconsult

Никогда не используйте IN или NOT IN с подзапросом; преобразуйте его в какое-либо соединение. Же существует.

Richard Deeming

У вас есть что-нибудь, чтобы подтвердить это?

Этот блог[^] предполагает, что коррелированная NOT EXISTS как правило, это лучшее решение. Полученные результаты также свидетельствуют о том, что NOT IN работает лучше, чем a LEFT JOIN.

jgakenhe

Я бы запустил план выполнения (погуглил его) и посмотрел, где он висит. Затем я бы поставил индекс на Match_Flag, потому что это запрашивается в предложении WHERE для большого количества записей. И если вы должны использовать NOT IN, то поместите его последним, так как набор данных должен быть небольшим к тому времени, когда он туда попадет.

План выполнения и индексы: http://www.codeproject.com/Articles/190263/Indexes-in-MS-SQL-Server

jaket-cp

Мне просто было интересно, будет ли большая выгода в том, чтобы иметь индекс Match_Flag, если существуют только два возможных значения " Y " и "N".
Я бы предложил поместить кластеризованный индекс в Столбцы Store_Range_Grp_Id, Range_Event_Id.

Как я уже сказал, просто интересно, вот и все...

CHill60

Согласен - не стоит на Match_Flag, обязательно индексируйте идентификаторы

Richard Deeming

Однако, если вы всегда запрос на получение Match_Flag = 'Y', отфильтрованный индекс может быть полезен.

CHill60

Очень хороший момент, и я все время забываю об этом. Я отредактировал свое решение (и приписал вам)

3 Ответов

Рейтинг:
20

CHill60

Как было предложено PIEBALDconsult заменить WHERE с присоединением
напр.

LEFT join Last_Authorised_Range lar on lar.Range_Event_Id = srg.Range_Event_Id
WHERE lar.Range_Event_Id is null


Индексы на полях идентификаторов в таблицах также должны помочь.

Как указывает член 10454138, нет никакой большой выгоды в том, чтобы иметь индекс на Match_Flag если есть только два значения

[EDIT] что касается моего последнего пункта в столбце, который имеет только два значения - @RichardDeeming сделал отличную точку зрения в комментарии выше. Если вы всегда отправляемся на поиски Match_Flag='Y' затем с помощью отфильтрованного индекса будет принесите улучшение производительности - ссылка Введение в отфильтрованные индексы SQL Server[^]


Member 11706445

как использовать отфильтрованный индекс?

CHill60

Есть примеры по ссылке в моем решении

Рейтинг:
2

Member 11706445

Привет всем, я действительно использовал левое соединение после удаления предложения Not IN, но это также не сработало для меня. Кластеризованные индексы уже есть в Столбцах идентификаторов обеих таблиц


Рейтинг:
1

Member 14603062

HI Write не существует, а также проверьте условие соединения левая боковая таблица должна содержать меньше записей.