SubSonic - Генерация SQL использует nvarchar вместо varchar, который вызывает сканирование индекса вместо поиска
Я использую шаблон SubSonic SimpleRepository для своего приложения. В VS2010 я создал проект ASP.NET WebForms, указывающий на базу данных SQL 2000.
У меня возникла проблема, когда SubSonic всегда использует nvarchar в параметризованных запросах вместо varchar. Это заставляет SQL выполнять сканирование индекса вместо поиска индекса. Я взял SQL из Profiler и изменил его, чтобы сделать параметры varchar похожими на поля таблицы, и он выполняется очень быстро (<1 секунда против 8 секунд).
SubSonic Query от Profiler
exec sp_executesql N'SELECT [t0].[ADDRESS_L1], [t0].[ADDRESS_L2], [t0].[ADDRESS_L3], [t0].[CITY], [t0].[COUNTRY] FROM [aveadmin].[SAPADD] AS t0 WHERE (([t0].[SITE_ID] = @p0) AND ((([t0].[ADDRESS_TYPE] = @p1) AND 1 <> 0) OR (([t0].[ADDRESS_TYPE] = @p2) AND 0 <> 0)))', N'@p0 nvarchar(16),@p1 nvarchar(2),@p2 nvarchar(2)', @p0 = N'BCF8A0A27E543EE1', @p1 = N'00', @p2 = N'03'
Измененный вручную запрос
exec sp_executesql N'SELECT [t0].[ADDRESS_L1], [t0].[ADDRESS_L2], [t0].[ADDRESS_L3], [t0].[CITY], [t0].[COUNTRY] FROM [aveadmin].[SAPADD] AS t0 WHERE (([t0].[SITE_ID] = @p0) AND ((([t0].[ADDRESS_TYPE] = @p1) AND 1 <> 0) OR (([t0].[ADDRESS_TYPE] = @p2) AND 0 <> 0)))', N'@p0 varchar(16),@p1 varchar(2),@p2 varchar(2)', @p0 = N'BCF8A0A27E543EE1', @p1 = N'00', @p2 = N'03'
SITE_ID
а также ADDRESS_TYPE
являются varchars
, Есть ли способ заставить запрос использовать varchar
вместо nvarchar
?
2 ответа
Есть ли способ заставить запрос использовать varchar вместо nvarchar?
Вам придется изменить исходный код SubSonic, чтобы изменить это поведение.
[Предыдущий ответ правильный - подробности следуют.]
Использование nvarchar жестко закодировано в функции GetNativeType() в Sql2005Schema.cs. это достаточно легко исправить и восстановить. Эй, это OSS! Для этого и нужен исходный код!
Вот код
case DbType.AnsiString:
case DbType.AnsiStringFixedLength:
case DbType.String:
case DbType.StringFixedLength:
return "nvarchar";
Теоретически, сгенерированный код (см. SQLServer.ttinclude) фактически генерирует DbType.AnsiString и DbType.String как отдельные типы. Должна быть возможность разделить оператор switch и сгенерировать "varchar" для одного и "nvarchar" для другого. Может быть, автор думал, что это не имеет значения. Я предлагаю вам попробовать (но это может нарушить юнит-тесты).