Где предложение для просмотра с использованием подзапроса с временной таблицей занимает исключительно много времени

Когда я использую select * from view where столбец в (xxxx) и использую подзапрос, который представляет собой простой список идентификаторов, его выполнение занимает почти в 1000 раз больше времени, чем просто ввод списка чисел, пример ниже.

A) занимает 0 мс для выполнения

SELECT Name FROM TMS.dbo.vPerson p WHERE p.personid IN (1,2,3,4)

B) занимает 3200 мс для выполнения

SELECT personid INTO #persons FROM  tcPerson p WHERE p.personid IN (1,2,3,4)
SELECT Name FROM TMS.dbo.vPerson p 
WHERE p.personid IN (SELECT personid FROM #persons)

Я каждый раз очищал кеш, но, похоже, нет веской причины, почему это занимает так много времени.

временная таблица буквально представляет собой список из 4 идентификаторов. его созданием можно пренебречь, а подбором значений в запросе where можно пренебречь

Вся помощь будет высоко оценена.


person McShep    schedule 16.03.2016    source источник
comment
Немного запутался, A делает 1 запрос, B делает 5... (ваш последний оператор имеет 3 запроса в целом)   -  person BugFinder    schedule 17.03.2016
comment
правда, есть 4 выбора, однако выбор персоны отдельно занимает не более 1 мс, это оставит еще 3000 секунд для учета.   -  person McShep    schedule 17.03.2016
comment
Хорошо, но некоторые linq на самом деле не выполняются в строке, на которой вы их пишете ... поэтому A, возможно, еще не обработал linq. вам нужно будет получить к нему доступ. Поместите строку секундомера и найдите, какой из ваших запросов занимает время, потому что A не похож на B... первая строка B, конечно... но она все еще находится в другом конечном контейнере.. один может быть локальной памятью, другой a удаленный удаленный сильно загруженный сервер sql без индексов..   -  person BugFinder    schedule 17.03.2016
comment
это внутри хранимой процедуры, linq не используется. Однако, чтобы подробнее остановиться на временной таблице, ее создание можно игнорировать, а выбор значений в запросе where незначителен.   -  person McShep    schedule 17.03.2016
comment
Хорошее замечание по linq - я думал, что в списке есть c # - хорошо ... так в чем разница между vPerson и tcPerson? поскольку tcPerson существует только в B   -  person BugFinder    schedule 17.03.2016
comment
Сколько человек в основной таблице (tcPerson?) и есть ли индекс для personid? Как ВЗГЛЯД?   -  person Shnugo    schedule 17.03.2016
comment
Определения таблиц (включая индексы) вместе с планами запросов обычно необходимы для настройки производительности.   -  person Tom H    schedule 17.03.2016
comment
это все действительные точки, размер таблицы составляет около 1 миллиона, планы выполнения идентичны для обоих. И есть индексы на personid, однако, поскольку я использую индексы sql 2008, их нельзя добавить в представление (я не использую корпоративную версию)   -  person McShep    schedule 17.03.2016
comment
отсутствие индекса наверняка объяснило бы разницу в скорости   -  person BugFinder    schedule 17.03.2016
comment
Но я не уверен, почему использование выбора во временной таблице для извлечения 4 значений приводит к тому, что это занимает гораздо больше времени, чем простой ввод этих четырех значений?   -  person McShep    schedule 17.03.2016
comment
Что, если вы используете EXISTS вместо IN   -  person FLICKER    schedule 17.03.2016
comment
1. Try существует вместо IN; 2. Сравните фактические планы запросов (включая фактический план) между временной таблицей и запросами с явными значениями и сравните фактическое и расчетное количество строк.   -  person Nick.McDermaid    schedule 17.03.2016


Ответы (1)


Это ваш запрос:

SELECT Name
FROM TMS.dbo.vPerson p 
WHERE p.personid IN (SELECT personid
                     FROM TMS.dbo.tcPerson p
                     WHERE p.personid IN (SELECT personid FROM #persons)
                    )

Иногда IN труднее оптимизировать, чем другие версии запроса. Вы можете сказать, посмотрев на план выполнения. Я отмечаю, что этот запрос эквивалентен:

SELECT Name
FROM TMS.dbo.vPerson p 
WHERE p.personid IN (SELECT personid FROM TMS.dbo.tcPerson p) AND
      p.person_id IN (SELECT personid FROM #persons)

Вложенные подзапросы не нужны. Этот запрос должен подойти, если у вас есть индексы на tcPerson(personid) и #persons(personid).

person Gordon Linoff    schedule 16.03.2016
comment
фактическая временная таблица получена из гораздо большего запроса, в результате которого возвращаются только значения for. Если я возьму эти 4 значения и запущу отдельно, я получу эквивалент вышеизложенного, однако это все еще действительная точка - person McShep; 17.03.2016
comment
При повторном чтении я заметил, что вы правы в том, что мне не нужны идентификаторы выбора подзапроса и обновлены соответственно. Однако проблема все еще присутствует в том, что выбор из временной таблицы для предоставления списка из 4 идентификаторов в предложение where принимает представление много бездельничать - person McShep; 17.03.2016