Я бы предположил, что когда запрос включает TOP n, ядро базы данных будет запускать запрос, игнорируя предложение TOP, а затем в конце просто сократит этот результат до n запрошенных строк. Графический план выполнения, кажется, указывает на то, что это так - TOP является «последним» шагом. Но, похоже, что-то еще происходит.
То, как сформулировано выше, заставляет меня думать, что у вас может быть неправильное представление о том, как выполняется запрос. Оператор в плане запроса не является шагом (где полный набор результатов предыдущего шага оценивается следующим.
SQL Server использует конвейерную модель выполнения, где каждый оператор предоставляет такие методы, как Init () , GetRow () и Close () . Как следует из названия GetRow () , оператор создает одну строку за раз по требованию (как того требует его родительский оператор). Это задокументировано в справочнике по логическим и физическим операторам Books Online , более подробно в моем блоге « Почему планы запросов выполняются задом наперед» . Эта рядовая модель необходима для формирования интуитивной интуиции при выполнении запросов.
У меня вопрос, как (и почему) предложение TOP
n влияет на план выполнения запроса?
Некоторые логические операции, такие как TOP
, полусоединения и FAST n
подсказки запросов, влияют на то, как оптимизатор запросов обходится альтернативам плана выполнения. Основная идея заключается в том, что одна возможная форма плана может возвращать первые n строк быстрее, чем другой план, который был оптимизирован для возврата всех строк.
Например, объединение индексированных вложенных циклов часто является самым быстрым способом возврата небольшого числа строк, хотя объединение хешей или объединение со сканированием может быть более эффективным на больших наборах. Оптимизатор запросов рассуждает об этих вариантах, устанавливая цель строки в определенной точке логического дерева операций.
Цель строки изменяет способ определения альтернатив плана запроса. Суть его в том, что оптимизатор начинает с того, что каждый оператор оценивает стоимость, как если бы требовался полный набор результатов, устанавливает целевую строку в соответствующей точке, а затем возвращается обратно к дереву плана, оценивая количество строк, которые он ожидает проверить. встретить цель строки.
Например, логика TOP(10)
устанавливает целевую строку в 10 в конкретной точке логического дерева запросов. Затраты операторов, ведущих к цели строки, модифицируются, чтобы оценить, сколько строк им нужно произвести для достижения цели строки. Этот расчет может стать сложным, так что все это легче понять с помощью полностью проработанного примера и аннотированных планов выполнения. Цели строк могут влиять не только на выбор типа соединения или на то, предпочтительнее ли поиск и поиск, чем на сканирование. Подробнее об этом здесь .
Как всегда, план выполнения, выбранный на основе цели строки, зависит от рассуждений оптимизатора и качества предоставляемой ему информации. Не каждый план с целью получения строк на практике будет производить необходимое количество строк быстрее, но в соответствии с моделью калькуляции это будет происходить.
В тех случаях, когда план целей строки оказывается не быстрым, обычно есть способы изменить запрос или предоставить оптимизатору более точную информацию, чтобы лучше подходил естественно выбранный план. Какой вариант подходит в вашем случае, конечно, зависит от деталей. Функция цели строки, как правило, очень эффективна (хотя есть ошибка, на которую нужно обращать внимание при использовании в параллельных планах выполнения).
Ваш конкретный запрос и план могут не подходить для подробного анализа здесь (во всех случаях, если хотите, предоставьте фактический план выполнения), но, надеюсь, идеи, изложенные здесь, позволят вам продвинуться вперед.
ORDER BY
пункт. ДобавляяTOP
изменения, где в плане происходит такая сортировка, но я больше обеспокоен тем, как это влияет на количество выполнений поиска индекса по таблице B ... (конечно, эти два могут быть связаны - я не знаю)