Зачем использовать Select Top 100 Percent?

82

Я понимаю, что до SQL Server 2005 вы могли «обмануть» SQL Server, чтобы разрешить использование порядка в определении представления, также включив его TOP 100 PERCENTв предложение SELECT . Но я видел другой код, который я унаследовал, который использует SELECT TOP 100 PERCENT... в динамических операторах SQL (используется в ADO в приложениях ASP.NET и т. Д.). Есть ли этому повод? Разве результат не такой же, как без учета TOP 100 PERCENT?

Эд Шембор
источник
5
возможно, здесь происходит какое-то построение оператора: «SELECT TOP {0} PERCENT ...»
Майкл Петротта,
Ваше первое предложение стало ответом на один из моих скрытых вопросов.
Мухаммад Ашикуззаман
Я использую верхний 99,9999999 PERCENT, и он всегда работает. Это достаточно близко. Я обычно добавляю цифры «9» в зависимости от ожидаемого количества записей. Больше записей, больше девяток, и это всегда работает. Я использовал по SQL 2008 для SQL 2017.
педи

Ответы:

51

Он использовался для « промежуточной материализации (поиск в Google) »

Хорошая статья: Адам Мачаник: Изучение секретов промежуточной материализации

Он даже поднял MS Connect, чтобы это можно было сделать более чистым способом.

Я считаю, что «неплохо по своей сути», но не используйте его, если не уверены на 100%. Проблема в том, что он работает только в то время, когда вы это делаете, и, вероятно, не позже (уровень исправления, схема, индекс, количество строк и т. Д.) ...

Пример работы

Это может потерпеть неудачу, потому что вы не знаете, в каком порядке оцениваются вещи

SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1 AND CAST(foo AS int) > 100

И это также может потерпеть неудачу, потому что

SELECT foo
FROM
    (SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1) bar
WHERE
    CAST(foo AS int) > 100

Однако в SQL Server 2000 этого не было. Внутренний запрос оценивается и помещается в буфер:

SELECT foo
FROM
    (SELECT TOP 100 PERCENT foo From MyTable WHERE ISNUMERIC (foo) = 1 ORDER BY foo) bar
WHERE
    CAST(foo AS int) > 100

Обратите внимание, это все еще работает в SQL Server 2005

SELECT TOP 2000000000 ... ORDER BY...
gbn
источник
Почему не удается выполнить второй запрос? Потому что внутренний запрос не (обязательно) полностью оценен?
Kenny Evitt
Эта вторая ссылка объясняет, почему создание временных таблиц иногда приводит к значительному повышению производительности!
Kenny Evitt
41

TOP (100) PERCENT совершенно бессмысленен в последних версиях SQL Server, и он (вместе с соответствующим ORDER BY в случае определения представления или производной таблицы) игнорируется обработчиком запросов.

Вы правы, когда-то это можно было использовать как трюк, но даже тогда это было ненадежно. К сожалению, некоторые графические инструменты Microsoft включают этот бессмысленный пункт.

Что касается того, почему это может появиться в динамическом SQL, я понятия не имею. Вы правы в том, что для этого нет причин, и результат будет таким же без него (и снова, в случае определения представления или производной таблицы, без предложений TOP и ORDER BY).

Стив Касс
источник
Это неправда; см. эту ссылку из ответа @gbn для подробностей.
Kenny Evitt
4
Ссылка, на которую вы ссылаетесь, ничего не говорит о SELECT TOP (100) PERCENT .. ORDER BY, что бессмысленно. В ссылке упоминается использование SELECT TOP (2147483647) .. ORDER BY. В настоящее время оптимизатор SQL Server исключает SELECT TOP (100) PERCENT .. ORDER BY, поскольку это бессмысленно. Эта комбинация всегда определяет тот же набор строк, что и SELECT, без TOP / ORDER BY. В настоящее время оптимизатор не пытается определить, содержит ли 2147483647 все строки, поэтому в этом случае он не исключает комбинацию TOP - ORDER BY.
Стив Касс
2
В ссылке действительно упоминается TOP (100) PERCENT: «... Я мог бы попытаться принудительно выполнить промежуточную материализацию производной таблицы без временной таблицы, используя TOP 100 PERCENT в сочетании с ORDER BY. К сожалению, команда оптимизатора запросов SQL Server решила, что это не так» Это хорошая идея, и теперь оптимизатор игнорирует такие попытки ». Фактически, он поддерживает вас.
Кенни Эвитт 02
Я бы отменил свой голос против, если бы мог . [Если вы отредактируете свой ответ, я буду поддерживать его.]
Кенни Эвитт 02
1
Вы, вероятно, сбиты с толку, потому что я передумал; мой первый комментарий был неправильным; вы правы.
Кенни Эвитт 02
23

... разрешить использование ORDER BY в определении представления.

Это плохая идея. Для представления никогда не должно быть определено ORDER BY.

ORDER BY влияет на производительность - использование представления означает, что ORDER BY появится в плане объяснения. Если у вас есть запрос, в котором представление присоединяется к чему-либо в непосредственном запросе или упоминается во встроенном представлении (факторинг CTE / подзапроса) - ORDER BY всегда запускается до окончательного ORDER BY (при условии, что он был определен). Нет никакой пользы от упорядочивания строк, которые не являются окончательным набором результатов, если запрос не использует TOP (или LIMIT для MySQL / Postgres).

Рассматривать:

CREATE VIEW my_view AS
    SELECT i.item_id,
           i.item_description,
           it.item_type_description
      FROM ITEMS i
      JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
  ORDER BY i.item_description

...

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM my_view t
ORDER BY t.item_type_description

... эквивалентно использованию:

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM (SELECT i.item_id,
                 i.item_description,
                 it.item_type_description
            FROM ITEMS i
            JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
        ORDER BY i.item_description) t
ORDER BY t.item_type_description

Это плохо, потому что:

  1. В примере сначала упорядочивается список по описанию элемента, а затем он переупорядочивается на основе описания типа элемента. При первой сортировке ресурсы тратятся впустую - работа как есть не означает, что она работает:ORDER BY item_type_description, item_description
  2. Из-за инкапсуляции не очевидно, что упорядочивает представление. Это не означает, что вы должны создавать несколько представлений с разными порядками сортировки ...
OMG Пони
источник
6

Если нет ORDER BYпункта, то TOP 100 PERCENTэто избыточно. (Как вы упомянули, это был трюк с видами)

[Надеюсь, оптимизатор все это оптимизирует.]

Митч Уит
источник
5

Я видел другой код, унаследованный мной, который использует SELECT TOP 100 PERCENT.

Причина этого проста: Enterprise Manager пытался быть полезным и форматировал ваш код, чтобы включить это за вас. Не было никакого смысла пытаться удалить его, потому что он действительно ничего не повредил, и в следующий раз, когда вы захотите его изменить, EM вставит его снова.

Джоэл Кохорн
источник
4

Думаю, без причины, кроме безразличия.

Такие строки запроса обычно генерируются графическим инструментом запросов. Пользователь объединяет несколько таблиц, добавляет фильтр, порядок сортировки и проверяет результаты. Поскольку пользователь может захотеть сохранить запрос как представление, инструмент добавляет ТОП 100 ПРОЦЕНТОВ. Однако в этом случае пользователь копирует SQL в свой код, параметризует предложение WHERE и скрывает все на уровне доступа к данным. Без ума, вне поля зрения.

Питер Радоккья
источник
1

Пожалуйста, попробуйте следующее, надеюсь, это сработает для вас.

      SELECT TOP
              ( SELECT COUNT(foo) 
                  From MyTable 
                 WHERE ISNUMERIC (foo) = 1) * 
                  FROM bar WITH(NOLOCK) 
              ORDER BY foo
                 WHERE CAST(foo AS int) > 100
               )
Лакшминараян Э.
источник
1

Ошибка говорит сама за себя ...

Msg 1033, уровень 15, состояние 1, процедура TestView, строка 5 Предложение ORDER BY недействительно в представлениях, встроенных функциях, производных таблицах, подзапросах и общих табличных выражениях, если также не указаны TOP, OFFSET или FOR XML.

Не используйте TOP 100 PERCENT, используйте TOP n, где N - число

ТОП 100 ПРОЦЕНТОВ (по причинам, которые я не знаю) игнорируется SQL Server VIEW (версии после 2012 года), но я думаю, что MS сохранила его по причинам синтаксиса. TOP n лучше и будет работать внутри представления и сортировать его так, как вы хотите, когда представление используется изначально, но осторожны .

Фанданго68
источник
0

Я бы предположил, что вы можете использовать в результате переменную, но, помимо получения элемента ORDER BY в представлении, вы не увидите выгоды от неявного указания «TOP 100 PERCENT»:

declare @t int
set @t=100
select top (@t) percent * from tableOf
Лорен Гленн
источник
2
Вопрос Why use Select Top 100 Percentне в том, чтобы получить переменное количество процентов.
bummi
0

Просто попробуйте, это само по себе объясняет. Вы не можете создать представление с ORDER BY, кроме случаев, когда ...

CREATE VIEW v_Test
         AS
           SELECT name
             FROM sysobjects
         ORDER BY name
        GO

Msg 1033, уровень 15, состояние 1, процедура TestView, строка 5 Предложение ORDER BY недействительно в представлениях, встроенных функциях, производных таблицах, подзапросах и общих табличных выражениях, если также не указаны TOP, OFFSET или FOR XML.

Джон Брюстер
источник