Эффект производительности при использовании TOP 1 в запросе SELECT - PullRequest
19 голосов
/ 17 сентября 2009

У меня есть таблица User, в которой есть столбцы Имя пользователя и Приложение. Имя пользователя может повторяться, но комбинация Имя пользователя + Приложение уникальна, но у меня нет уникального ограничения, установленного для таблицы (для производительности)

Вопрос: будет ли (с точки зрения производительности) разница между:

SELECT * FROM User where UserName='myuser' AND Application='myapp'

И -

SELECT TOP 1 * FROM User where UserName='myuser' AND Application='myapp'

Поскольку комбинация Имя пользователя + Приложение уникальна, оба запроса всегда будут возвращать не более одной записи, поэтому TOP 1 не влияет на результат. Я всегда думал, что добавление TOP 1 действительно ускорит процесс, так как сервер sql перестанет смотреть после того, как он найдет одно совпадение, но недавно я прочитал в статье, что использование TOP на самом деле замедлит работу, и его рекомендуется избегать, хотя они этого не объяснил почему.

Есть комментарии?

Спасибо! Андрей

Ответы [ 4 ]

17 голосов
/ 17 сентября 2009

Если в результатах более одной строки и нет предложения ORDER BY, «TOP 1» экономит тонну работы для сервера. Если есть пункт order by, сервер все равно должен материализовать весь набор результатов в любом случае, и если есть только одна строка, это ничего не меняет.

14 голосов
/ 17 сентября 2009

Вы можете получить некоторую разницу в производительности, просто используя top, но реальную производительность вы получите, используя индексы.

Если у вас есть индекс для полей UserName и Application, базе данных даже не нужно касаться таблицы, пока она не изолирует одну запись. Кроме того, из статистики таблицы уже будет известно, что значения являются уникальными, поэтому использование top не имеет значения.

5 голосов
/ 17 сентября 2009

Я думаю, что это зависит от плана выполнения запроса, который генерирует SQL ... В прошлом на предыдущих версиях SQL Server я видел, как использование избыточного «TOP» давало определенные преимущества в производительности со сложными запросами со многими объединениями. Но точно не во всех случаях.

Полагаю, лучший совет, который я могу дать, это попробовать его в каждом конкретном случае.

2 голосов
/ 17 сентября 2009

вы говорите, что не применяете ограничение, что означает отсутствие уникального индекса (UserName, Application) или (Application, UserName). Может ли запрос использовать путь доступа, который ищет на UserName или Application? Другими словами, индексируется ли какой-либо из этих двух столбцов? Если да, то план выберет наиболее избирательный индекс, который будет проиндексирован, и выполнит сканирование диапазона, возможно, вложенный цикл с поиском закладок, если индекс не кластеризован, а затем фильтр. Топ 1 остановит запрос после сопоставления первого фильтра, но имеет ли это значение, зависит от количества данных (сколько записей найдет сканирование диапазона и сколько удовлетворяет фильтр).

Если индекс отсутствует, он будет выполнять полное кластерное сканирование, несмотря ни на что. Топ 1 остановит сканирование при первом совпадении, будь то после обработки 1 записи или после обработки 999 мил. записи зависят от фактического имени пользователя и приложения ...

Единственное, что даст реальное различие, - это то, что запрос может выполнить поиск обоих значений, т.е. иметь индекс покрытия. Ограничение будет применяться именно через такой покрывающий индекс. Другими словами: отключив ограничение, предположительно для производительности записи, будьте готовы заплатить цену при чтениях. Это важно читать? Делали ли вы какие-либо измерения, чтобы подтвердить, что дополнительная индексная запись ограничения будет серьезно снижать производительность?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...