SQL ЛУЧШИЕ 5000 быстрее, чем нормальный вопрос меньше чем с 5000 рядов результата?

Я заметил некоторое странное поведение:

Управление этим вопросом:

SELECT TOP 5000  t1.f1,t1.f2,t1.f3 
FROM t1
JOIN t2 on t1.f1 = t2.f1
WHERE t2.f1 IS NOT NULL AND (t1.f5 != t2.f3)

Результаты в 3447 рядах за 2 секунды.

Управление этим:

SELECT t1.f1,t1.f2,t1.f3 
FROM t1
JOIN t2 on t1.f1 = t2.f1
WHERE t2.f1 IS NOT NULL AND (t1.f5 != t2.f3)

Пробеги навсегда, пока я не останавливаю его (по крайней мере 120 минут!!).

Стол t1 и t2 держится об отчетах 500k.

Я всегда принимал ВЕРШИНУ , заявление не имело значения, лежит ли общее количество рядов ниже того числа, однако, кажется, есть очень значительная разница. Действительно ли это нормально (если так, почему), или это - просто счастливая случайность?

ОТРЕДАКТИРУЙТЕ:

Согласно просьбе:

t1:

CREATE TABLE [dbo].[t1](
    [f1] [int] NOT NULL,
    [f2] [varchar](10) NULL,
    [f3] [varchar](4) NULL,
    [f4] [int] NOT NULL,
    [f5] [varchar](max) NULL,
 CONSTRAINT [PK_t1] PRIMARY KEY CLUSTERED 
(
    [f1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

f2:

CREATE TABLE [dbo].[t2](
    [f1] [nchar](10) NOT NULL,
    [f2] [nchar](10) NOT NULL,
    [f3] [varchar](max) NOT NULL,
    [f4] [nchar](10) NULL,
    [f5] [date] NULL,
    [f6] [date] NULL,
    [f7] [nchar](1) NULL,
 CONSTRAINT [PK_t2] PRIMARY KEY CLUSTERED 
(
    [f1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Планы выполнения:

With top: Execution with top

Without top: Exec w/o top

Рассмотрение этого, я должен был бы прийти к заключению, что сортировка (ПОЧЕМУ это делает это??) вызывает задержку... Вы согласились бы?

Edit2: as requested, execution plan with loops option without top: enter image description here

14
добавлено отредактировано
Просмотры: 2
nl ja de
Вопросы: 1) это планы Esitmated или Фактические планы? 2) что является предполагаемым (и фактический, при наличии), количество ряда от двух Кластерных индексов Ищет/Ищет в обеих версиях. 3) (очень важный), Каков предупредительный знак на "Избранных" символах, указывающих? Пропылесосьте по нему с вашим курсором, чтобы видеть детали. Если это говорит "Недостающую Статистику" тогда, который вероятен проблема.
добавлено автор RBarryYoung, источник
@shahkalpesh: На самом деле это зависит, на котором плане запросов это обосновывается на. В этом случае это действительно делает это, но в других случаях это может не начать возвращать ряды немного ранее, чем неглавный вопрос.
добавлено автор RBarryYoung, источник
@saratis... Нет. Вершина относится к набору результатов, не входным таблицам.
добавлено автор Gordon Linoff, источник
@shahkalpesh... Хорошая выгода. То условие избыточно, потому что ПУСТЫЕ УКАЗАТЕЛИ провалили бы тест соединения. И, для вашего второго вопроса, нет. База данных не прячет результаты про запас обязательно, хотя, используя заказ или группа она, возможно, должна была бы произвести почти весь набор результатов прежде, чем возвратить что-либо.
добавлено автор Gordon Linoff, источник
Вы пробовали выбор (соединение петли) ? Это помогает?
добавлено автор Nikola Markovinović, источник
Заказ столов в из пункта . Если вы говорите от t2 внутреннего объединения t1... , я ожидаю видеть exacly тот же самый план выполнения. Отметьте: I' m использующие комментарии, потому что I' m не абсолютно уверенный, что моя попытка объяснения жизнеспособна.
добавлено автор Nikola Markovinović, источник
Столы полностью изменены. Это должно составить идентичный план если вы обратный порядок столов в из пункта. Если I' m правильный, причина вершина производит намного более быстрый вопрос, то, потому что оптимизатор видит, что только требуется 1% рядов (потому что f1 уникален), и использует вложенный цикл, чтобы восстановить сначала 5000 и расследование t2, ожидая тот t1.f5! = t2.f3 быть главным образом верным. Во втором случае это ожидает возвращать почти 500K ряды, таким образом, это оптимизирует для слияния, которое требует к наборам, чтобы быть в порядке. Проблема здесь состоит в том, что f1 в обоих столах имеют другой тип и таким образом виды по-другому.
добавлено автор Nikola Markovinović, источник
Не могли бы Вы опубликовать план выполнения с выбором петли?
добавлено автор Nikola Markovinović, источник
О, хорошо. Тот же самый план, но различный результат вне моей досягаемости. Но если бы я был на вашем месте, то я видел бы, могу ли я преобразовать f1 из t2 к интервалу и видеть, работает ли это лучше. Это должно.
добавлено автор Nikola Markovinović, источник
@GordonLinoff: Спасибо за исправление меня.
добавлено автор shahkalpesh, источник
@saratis: Так, удаление t2.f1 ЯВЛЯЕТСЯ NOT NULL didn' t имеют значение?
добавлено автор shahkalpesh, источник
Эксперты по DB: исправьте меня если неправильно. <�кодовая> ВЕРШИНА начинает течь результаты, как только это находит любые ряды с соответствием критериям. Для другого сценария это найдет все соответствующие ряды и свалит его, как только это сделано полностью. То правильное предположение?
добавлено автор shahkalpesh, источник
Это условие t2.f1, NOT NULL значащий? t1.f1 будет пустым вообще?
добавлено автор shahkalpesh, источник
Вы смотрели на планы выполнения?
добавлено автор Aaron Bertrand, источник
Ваши два , ГДЕ s кажутся другими мне: каждый имеет "t1.f3! = t2.f3", но другой имеет "t1.f5". Если количество элементов этих двух колонок отличается (или они внесены в указатель по-другому), который будет, конечно, влиять на планировщика вопроса.
добавлено автор LSerni, источник
@anothershrubery от того, что я понимаю, лучшие 5000 только влияние набор результатов, не входной набор, так, чтобы не имел значения. Я, однако, не эксперт.
добавлено автор Derk Arts, источник
@NikolaMarkovinović OMG, другая ошибка, я очень не хочу анонимизировать материал, конечно столы находятся в том же самом заказе, я просто потянул этикетки неправильно...
добавлено автор Derk Arts, источник
@NikolaMarkovinović, Что делает вас, означают ' reversed'? я don' t действительно понимают ваше объяснение. Вы могли, возможно, сформулировать это более ясно как отдельный ответ, так, чтобы мы вышли из этого списка комментария и могли обсудить его отдельно...
добавлено автор Derk Arts, источник
@RBarryYoung 1) Для вопроса с Вершиной это - фактический план, для других, я can' t получают фактический план, потому что он никогда не заканчивается. 2) Для f1: 486185, для f2: 487707 3) Предупреждения находятся в XML:
добавлено автор Derk Arts, источник
@NikolaMarkovinović Сделан. Этот бежал в течение 11 минут, когда я остановил его.
добавлено автор Derk Arts, источник
@NikolaMarkovinović попробовал это, он действительно изменяет план выполнения, чтобы посмотреть намного более сходно с ЛУЧШИМ 5000 один, но все еще не показывает результатов.
добавлено автор Derk Arts, источник
Возгласы жаль, отредактированный запрос 1, но не 2, они - на самом деле то же самое, кроме Верхней части.
добавлено автор Derk Arts, источник
@Brian отправил структуру и планы. Предположил бы, что вид создает проблему здесь.
добавлено автор Derk Arts, источник
Да t2.f1 было оставшимся от предыдущей версии вопроса, не должен иметь никакого влияния все же. Хороший, чтобы знать, что ВЕРШИНА только смотрит на набор результатов. Это действительно, однако, оставляет нас без объяснения.
добавлено автор Derk Arts, источник
Я просто сделал (спасибо не знало ту особенность). Из того, что я читал, я мог интерпретировать его как таковой, что вопрос сначала берет первые 5000 рядов t1. Если это так, это было бы очень нежелательно..
добавлено автор Derk Arts, источник
Если вы хотите помощь, публикуете таблицу и определения индекса, а также планы выполнения.
добавлено автор brian, источник
Запрос 1, ваш, где пункт сравнивает t1.f5. Запрос 2, ваш, где пункт сравнивает t1.f3
добавлено автор tgolisch, источник
Я могу пропускать значительную деталь здесь, но разве вы не сказали, что у t1 и t2 есть 500k ряды? That' s значительно больше чем 5000. Был бы это не объяснять различие. Очевидно, это должно выступить лучше, чем, каково это, но that' s различный вопрос.
добавлено автор anothershrubery, источник
"Лучшие 5000" будут произвольными, если у вас нет заказа, таким образом, ваше утверждение, что отбор вершины от t1 является нежелательным doesn' t имеют смысл мне. Если вы добавляете "заказ" на том, что важно для вас, который изменяет две работы вопросов?
добавлено автор user662852, источник

2 ответы

Проблема состоит в том, что ваши два стола, [t1] и [t2] имеют полностью отличающийся (и в основном несовместимый) типы данных для Объединяющего столбца, f1 .

Это лишает возможности Оптимизатор запросов производить точную оценку того, сколько рядов собирается соответствовать между эти два 500,000 столов ряда. Это, кажется, использует "предположение" по умолчанию, которое в этом случае является общим количеством по - оценка фактического номера (3477). Из-за этого, когда вы не используете ВЕРШИНУ, она думает, что это будет более эффективно к Виду и затем Слиянию ряды (O (NLogN)), чем сделать вложенные циклы (O (N^2)), потому что она не понимает, что (слияние) СОЕДИНЕНИЕ на самом деле устранит почти все ряды.

Когда у вас есть ЛУЧШИЕ 5000 на, это понимает, что Вложенные циклы лучше, потому что это будет отключено в не больше, чем 5000 (намного меньше, чем 500k^2 и еще меньше, чем 500k * Регистрация (500k)). Но в отличие от Вложенных циклов, Сортировка слиянием не может быть сделана с приращением, у нее должны быть все ряды для Вида сначала. Так отключая продукцию в 5000, не спас бы вас очень вообще, таким образом делая Вложенные циклы ясно лучшим выбором (даже с плохой оценкой СОЕДИНЕНИЯ).


Проблема корня здесь состоит в том, что колонка T2.f1 - NCHAR (10), который является действительно плохим выбором для чего-то, что похоже, она, как предполагается, содержит целое число. Лучшее решение состояло бы в том, чтобы изменить тип данных той колонки на INT.

Если по некоторым причинам вы не можете сделать этого, то в зависимости от вашей версии SQL Server, можно быть в состоянии закончить, управляют этим, добавляя сохраненный вычисляемый столбец, который вычисляет, INT преобразовал ценность [f1], и затем бросьте совместимый индекс на что . Это позволило бы и индексации и статистике работать снова на вопросы как это.

Как последнее прибежище вы могли также использовать Намек Вопроса. Я обычно не рекомендую им как, потому что они имеют тенденцию быть временными решениями та причина проблемы позже. Однако, если вы чувствовали, что это было вашим единственным выбором, затем добавление ВЫБОР (БЫСТРО 1000) до конца вас, вопрос, вероятно, работал бы.

13
добавлено
Когда я смотрю на главный план запросов и план запросов СОЕДИНЕНИЯ ПЕТЛИ, ясно, что его количество элементов (количество ряда) оценки существенно отличается. Это должно быть невозможно, если что-то еще значительное не изменилось. Попытайтесь извлечь планы запросов и выполнить два вопроса снова, друг прямо рядом с другом. Те rowcounts (от Кластерного индекса Ищут/Просматривают) должны соответствовать, и если так, тогда время выполнения должно соответствовать также. Если они не делают, то что-то глубже выключено и we' ll должен видеть больше детали в планах запросов.
добавлено автор RBarryYoung, источник
Ничего себе, я испытываю затруднения при понимании ответа:). Но некоторые вопросы. 1) , используя выбор петель на неглавном вопросе (план выполнения три) это также использует вложенные циклы, итак, почему это все еще настолько медленно. 2) Будет, изменяясь t1.f1 к интервалу, имеют значение? 3) <�у / код> t1.f1 и t2.f1 ДЕЙСТВИТЕЛЬНО есть почти 500k матчи, it' s просто другие критерии это don' t матч (в 3477 случаях), вы понимали это правильно? 4) там способ сделать это шоу вопроса результатами в минутах (w/o ВЕРШИНА)?
добавлено автор Derk Arts, источник
I' m жаль, я обычно использую MySql, можно ли объяснить мне, что я должен сделать?
добавлено автор Derk Arts, источник
I' m не уверенный имеют правильную причину различия между ЛУЧШИМИ 5000 вопросов и не ГЛАВНЫМ вопросом, но вами, решение определенно работает! Измененный типы в T2, чтобы соответствовать T1 (должен был усечь стол, чтобы сделать, которые происходят) и теперь вопрос бежит действительно быстро. Так Спасибо!
добавлено автор Derk Arts, источник

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

Я предположил бы, что эти две версии оптимизируются по-другому. Можно проверить это, как Аарон предполагает, смотря на планы выполнения. Моя обычная ставка - то, что медленная версия использует соединения вложенного цикла. Можно зафиксировать это с намеком оптимизатора, таким как:


option (MERGE JOIN, HASH JOIN)

Есть другие возможности. Возможно, эти столы обновляются, и у столов, оказалось, были полные блокировки таблицы, когда вы управляли вторым вопросом. Можно проверить это использование sp_who2 .

2
добавлено
Это удалось для меня! С 5 минут вниз к 2 секундам:)
добавлено автор Mixxiphoid, источник
выбор (СЛИЯНИЕ, ХЭШИРОВАНИЕ), кажется, не делает много.
добавлено автор Derk Arts, источник
Спасибо, столы не используются никем больше. Aaron' s комментарий принудил меня полагать, что вопрос только посмотрит на первые 5000 рядов t1, который не является, почему я хочу, конечно, я хочу первые 5000 рядов, к которым присоединяются. Я попробую ваш намек оптимизатора.
добавлено автор Derk Arts, источник