Табличный параметр имеет низкую производительность из-за сканирования таблицы - PullRequest
5 голосов
/ 02 декабря 2010

У меня есть приложение, которое передает параметры в процедуру в SQL. Одним из параметров является табличный параметр, содержащий элементы, которые необходимо включить в предложение where.

Поскольку к табличному параметру не прикреплена статистика, когда я присоединяю свой TVP к таблице с 2 миллионами строк, я получаю очень медленный запрос.

Какие у меня есть альтернативы?

Опять же, цель состоит в том, чтобы передать определенные значения процедуре, которая будет включена в предложение where:

выберите * из таблицы1, где идентификатор в (выберите идентификатор из @mytvp)

или

выбрать * из таблицы1 t1 присоединиться @mytpv tvp on t1.id = tvp.id

Ответы [ 5 ]

1 голос
/ 11 апреля 2012

У меня была та же проблема, что и для табличных параметров, но в моем контексте она была очень медленной.Я нашел решение, которое передавало список значений в виде строки, разделенной запятыми, в хранимую процедуру.Затем процедура произвела сравнение PATINDEX (...)> 0.Это было примерно в 1: 6 раз быстрее.

1 голос
/ 02 декабря 2010

Вы можете использовать временную таблицу с индексом для повышения производительности .... (при условии, что в вашем @mytvp имеется более двух записей)

непосредственно перед тем, как присоединиться к таблице, вы можете вставитьданные из переменной @mytvp во временную таблицу ...

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

CREATE TABLE #temp_employee_v3
    (rowID     int          not null  identity(1,1)
    ,lname     varchar (30) not null
    ,fname     varchar (30) not null
    ,city      varchar (20) not null
    ,state     char (2)     not null
    ,PRIMARY KEY (lname, fname, rowID)
    ,UNIQUE (state, city, rowID) )
1 голос
/ 02 декабря 2010

, хотя кажется, что для каждой строки в таблице 1 необходимо выполнить запрос один раз, EXISTS часто оптимизируется, чтобы быть более эффективным, чем JOIN или IN.Итак, попробуйте следующее:

select * from table1 t where exists (select 1 from @mytvp p where t.id=p.id)

также убедитесь, что t.id имеет тот же тип данных, что и p.id, а t.id имеет индекс.

0 голосов
/ 19 октября 2016

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

CREATE TYPE IdList AS TABLE ( Id UNIQUEIDENTIFIER NOT NULL PRIMARY KEY )

Однако , проверьте, улучшает ли это производительность в вашем случае, как и сейчас, эти индексы существуют при заполнении TVP, что может привести к эффекту счетчика в зависимости от сортировки вашего входаи / или если вы используете более одного столбца.

0 голосов
/ 02 декабря 2010

Как и для табличных переменных, табличные параметры не имеют статистики (см. Раздел «ограничения»);Оптимизатор запросов работает при условии, что они содержат только одну строку, что, если ваш параметр содержит много строк, может привести к неправильному плану запросов.

Один из способов повысить ваши шансы на лучший план -добавить перекомпиляцию уровня выписки;это должно позволить оптимизатору учитывать размер TVP при выборе плана.

select * from table1 t where exists (select 1 from @mytvp p where t.id=p.id) OPTION (RECOMPILE)

(включая предложение КМ)

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