Команда «С» медленнее, чем использование временной таблицы. Выберите * в # table1 из - PullRequest
0 голосов
/ 08 мая 2019

Почему следующий запрос намного быстрее?

Запрос 1:

    select distinct ID mid
INTO #t1
from A_Position a where a.situationdate=@SituationDate and 
    a.Portfolio_Name=@portfolio and a.Purpose=@purpose and ID!='TOTAL'

select distinct ID gid 
INTO #t2
from B_Position a where a.situationdate=@SituationDate and 
    a.Purpose=@purpose

select @check=COUNT(mid) from #t1 A INNER JOIN #t2 B ON A.mid = 
    B.gid

Запрос 1 намного быстрее запроса 2.

Запрос 2:

;With 
A as (
select distinct ID mid 
    from A_Position a where 
    a.situationdate=@SituationDate and a.Portfolio_Name=@portfolio and 
    a.Purpose=@purpose and ID!='TOTAL'), 

    B as(
select distinct ID gid 
    from B_Position a where 
    a.situationdate=@SituationDate and a.Purpose=@purpose)

select @check=COUNT(mid) from A INNER JOIN B ON A.mid = 
    B.gid

Запрос 3:

select @check=COUNT(*)  
        from (
    select distinct ID mid 
        from A_Position a where a.situationdate=@SituationDate and 
        a.Portfolio_Name=@portfolio and a.Purpose=@purpose and 
        ID!='TOTAL') A
    inner join (  select distinct ID gid 
        from B_Position a where 
        a.situationdate=@SituationDate and a.Purpose=@purpose) B on mid=gid

По сути, все три запроса имеют одинаковый результат, но выполнение запроса 1 занимает всего 1-2 секунды.Запрос 2 или 3, с другой стороны, выполняется более 10 минут.Почему такая огромная разница в способе написания кода?(Почему "С" медленнее)

Ответы [ 2 ]

1 голос
/ 08 мая 2019

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

Во-первых, вторые два одинаковы. Представление подзапросов в виде CTE или подзапросов не меняет план выполнения в SQL Server.

Почему версия временной таблицы быстрее? Простой ответ заключается в том, что он получает лучший план выполнения.

Но возникает вопрос. Причина в том, что алгоритм, используемый для объединения двух таблиц. В версиях CTE / подзапросов SQL Server должен угадать, сколько строк сгенерировано. Основываясь на этом числе, он выбирает лучший алгоритм.

В версии временной таблицы данные уже находятся в таблице, поэтому SQL Server не нужно угадывать.

Итак, временные таблицы могут создавать лучшие планы выполнения. Позвольте мне сделать несколько оговорок. Использование временных таблиц сопряжено с большими затратами - на самом деле данные должны где-то храниться. Это также ограничивает возможности для оптимизации (что в данном случае хорошо, но в других случаях этого не может быть).

Вы должны иметь возможность добавить подсказку для ускорения других версий. Я бы предположил что-то вроде OPTION (HASH JOIN).

Вы также можете настроить индексы для оптимизации всех трех версий.

0 голосов
/ 08 мая 2019

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

Второй и третий запросы, описанные выше, заранее выясняют, как лучше всего выполнить внутреннее объединение двух подмножеств. Но в этот момент они не знают, сколько данных находится в этих подмножествах, поэтому они догадываются, и в этом случае кажется, что они угадывают неправильно и выбирают действительно плохой метод. Возможно, он решил, что быстрее будет сначала присоединиться и отфильтровать позже, или использовать индекс, или что-то еще. Если вы посмотрите на планы выполнения, найдите биты, в которых ожидаемая и фактическая строки сильно отличаются.

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

...