2012-06-07 6 views
12

Я использую dapper-dot-net как ORM, и он производит следующий, медленно исполняемый (1700 мс), код SQL.sp_executesql медленный с параметрами

exec sp_executesql N'SELECT TOP 5 SensorValue FROM "Values" WHERE DeviceId IN (@id1,@id2) AND SensorId = @sensor AND SensorValue != -32768 AND SensorValue != -32767',N'@id1 bigint,@id2 bigint,@sensor int',@id1=139,@id2=726,@sensor=178 

Когда я изменяю этот код, удаляя параметры, запрос выполняется невероятно быстро (20 мс). Должно ли отсутствие этих параметров на самом деле сделать эту большую разницу и почему?

exec sp_executesql N'SELECT TOP 5 SensorValue FROM "Values" WHERE DeviceId IN (139,726) AND SensorId = 178 AND SensorValue != -32768 AND SensorValue != -32767' 
+0

Насколько велика таблица? Какие индексы у него есть? –

+1

Я ответил на аналогичный вопрос [здесь] (http://stackoverflow.com/a/15477956/11808). –

ответ

22

Добавить ВАРИАНТ (RECOMPILE) до конца

... AND SensorValue != -32767 OPTION (RECOMPILE) 

Я подозреваю, что вы испытываете «параметр нюхают»

Если это так, мы можем оставить его с опцией или рассмотреть альтернативные варианты

Обновление 1

В следующей статье вы познакомитесь с «параметрическим обнюхиванием» http://pratchev.blogspot.be/2007/08/parameter-sniffing.html

Я советую вам узнать, как вы входите и выходите, потому что это значительно улучшит понимание внутренних компонентов sql-сервера (что может укусить).

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

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

Update 2

Лучшее чтение у меня было на эту тему было в главе 32 называется «Параметр нюхать: ваш лучший друг ... кроме случаев, когда это не» грант FRITCHEY

Рекомендуется.

SQL Server MVP Deep Dives, Volume 2

+0

Конечно, что-то общее с индексированием. –

+0

это, кажется, сделало трюк, я должен держать это для каждого исключения или только один раз, чтобы перекомпилировать его? (примет ваши ответы после того, как я проведу несколько дополнительных тестов, спасибо) –

+0

@m__ Обновлен ответ. – buckley

3

Недавно я столкнулся с той же проблемой. Первое, что я сделал, это добавить индекс NonClustered Covering Index в столбцы в моей инструкции where.

Это улучшило время выполнения SQL, но когда dapper выполнял запрос, он все еще был медленным, на самом деле это было время.

Тогда я понял, что запрос генерируется Dapper проходил в параметре, как NVARCHAR (4000), где в качестве своей колонке таблицы БД была VARCHAR (80) это вызвало его, чтобы выполнить сканирование индекса вместо искать (Я предлагаю вам читать индексы, если это не имеет для вас смысла.).Осознав это, я обновил свой щеголеватый, где заявление должно быть так:

ГДЕ Ссылка = новообращенный (VARCHAR (80), @ Reference)

, выполняющему с где выше высказывании привело к индексу поиска и повышения производительности на 100%.

Просто для добавления: вариант (перекомпиляция) не работал для меня.

И после всей этой песни и танца, есть способ сказать щеголеватый, чтобы сделать это для вас по умолчанию:

Dapper.SqlMapper.AddTypeMap (TypeOf (строка), System.Data.DbType .AnsiString);

Это будет по умолчанию отображать любые строковые параметры в varchar (4000), а не в nvarchar (4000). Если вам требуется сравнение строк в Unicode, вы можете явно выполнить преобразование параметра.

 Смежные вопросы

  • Нет связанных вопросов^_^