Nested Loops Join

Пересказ статьи Bert Wagner. Visualizing Nested Loops Joins And Understanding Their Implications

О чем говорят нам физические операции соединения

Каждый имеет свой метод чтения плана выполнения при настройке медленных SQL-запросов. Я вначале предпочитаю смотреть на то, какие операции соединения используются:

Эти три иконки могут не представлять собой очевидные места для начала поиска проблем в медленных запросах, однако в особенно больших планах я люблю начинать с быстрого взгляда на операторы соединения, поскольку они позволяют нам многое понять из того, что SQL Server думает о ваших данных.

Эта серия публикаций состоит из трех частей, в которых мы изучим, как работает каждый алгоритм соединения, и что они могут рассказать об операторах в восходящем потоке данных на плане выполнения нашего запроса.

Соединения вложенными циклами

Nested Loops Join работает примерно так: SQL Server берет первое значение из первой таблицы (наша «внешняя» таблица выбирается сервером по умолчанию) и сравнивает его с каждым значением во второй «внутренней» таблице в поисках совпадения.

Когда проверено каждое значение из внутренней таблицы, SQL Server переходит к следующему значению во внешней таблице, и процесс повторяется до тех пор, пока для каждого значения из внешней таблицы не будет выполнено сравнение с каждым значением из внутренней таблицы.

Это описание представляет собой пример худшего варианта использования соединения вложенными циклами с точки зрения производительности. Существует несколько оптимизационных приемов, которые делают соединение более эффективным. Например, если строки внутренней таблицы отсортированы
по значениям соединения (поскольку имеется созданный вами индекс или сервер создал спул), SQL Server может обрабатывать строки значительно быстрей. Поскольку строки внутреннего входа отсортированы, это позволяет выполнять прямой поиск необходимых строк, сокращая общее число необходимых сравнений.

За более подробным объяснением происходящего внутри сервера и оптимизации nested loops joins вы можете обратиться к статье Крейга Фридмана.

Что выявляет соединение вложенными циклами?

Знание механизма работы nested loops join позволяет нам получить информацию о том, как оптимизатор воспринимает наши данные, и восходящих потоках данных операторов соединения, что помогает нам сосредоточить усилия на настройке производительности.

Вот несколько сценариев, которые вы можете принять во внимание, когда в следующий раз увидите использование nested loops join в вашем плане выполнения:

  • Nested loops join истенсивно использует CPU; в худшем случае, когда каждую строку требуется сравнить с каждой другой строкой, может потребоваться некоторое время. Когда вы видите nested loops join, это означает, что SQL Server, вероятно, думает, что один из двух входов относительно невелик.
    • И если один из входов относительно мал, отлично! Если, напротив, вы видите операторы потока, которые перемещают большие объемы данных, то возможны проблемы с неверной оценкой в этом месте плана, и потребуется обновить статистику/добавить индексы/переписать запрос, чтобы позволить SQL Server обеспечить лучшие оценки (и выбрать, возможно, более подходящий тип соединения).
  • Вложенные циклы иногда сопровождаются RID или key lookups (поиском закладок). Я всегда проверяю их наличие, поскольку они предоставляют некоторые возможности улучшения производительности:
    • Если имеется RID lookup, обычно бывает достаточно добавить кластеризованный индекс к соответствующей таблице, чтобы получить прирост производительности.
    • Если RID или key lookup присутствует, я всегда проверяю, какие столбцы возвращаются, чтобы увидеть, достаточно ли вместо этого использовать небольшой индекс (с включением столбца в ключ/столбец существующего индекса) или возможно ли изменить запрос так, чтобы он не возвращал эти столбцы (например, избавиться от SELECT *).
  • Nested loops join не требует сортировки входных данных. Однако производительность можно улучшить при помощи сортировки источника входных данных; SQL Server сможет выбрать более эффективный оператор, если оба входа отсортированы.
    • По меньшей мере, nested loops joins позволяют мне понять, что входные данные не сортированы в результате преобразования восходящих потоков данных или по причине отсутствия индексов.

Итак, хотя вложенные циклы в ваших планах всегда потребуют дальнейшего исследования, их присутствие и связанные с ними операторы могут дать вам полезную информацию о том, что SQL Server думает о ваших данных.

Добавить комментарий