Я хочу найти географические названия, которые начинаются с символов, введенных в поле поиска.Некоторые географические названия имеют альтернативные названия на других языках.Эти альтернативные имена хранятся в отдельной таблице.
GN_Name 1 - 0:N GN_AlternateName
(PK) GN_Name.GeoNameId == (FK) GN_AlternateName.GeoNameId
Я хочу сначала найти имя в GN_AlternateName.AlternateNameи если этого не существует, используйте соответствующее GN_Name.Name.
Я написал следующий запрос LINQ:
return (from name in db.GN_Name
where name.CountryCode == "se"
join alt in db.GN_AlternateName
on name.GeoNameId equals alt.GeoNameId into outer
from alt in outer.DefaultIfEmpty()
where ((alt.IsoLanguage == "sv" &&
alt.AlternateName.StartsWith(query)) ||
name.Name.StartsWith(query))
select new GeoNameModel {
Language = alt.IsoLanguage,
Name = (alt == null ? name.Name : alt.AlternateName),
FeatureClass = name.FeatureClass,
FeatureCode = name.FeatureCode,
GeoNameId = name.GeoNameId,
UniqueName = name.UniqueName,
UniqueCount = name.UniqueCount}).Take(HB.AutoCompleteCount);
Это переводит в следующий SQL:
exec sp_executesql N'SELECT
[Limit1].[GeoNameId] AS [GeoNameId],
[Limit1].[IsoLanguage] AS [IsoLanguage],
[Limit1].[C1] AS [C1],
[Limit1].[FeatureClass] AS [FeatureClass],
[Limit1].[FeatureCode] AS [FeatureCode],
[Limit1].[UniqueName] AS [UniqueName],
[Limit1].[UniqueCount] AS [UniqueCount]
FROM ( SELECT TOP (5)
[Extent1].[GeoNameId] AS [GeoNameId],
[Extent1].[FeatureClass] AS [FeatureClass],
[Extent1].[FeatureCode] AS [FeatureCode],
[Extent1].[UniqueName] AS [UniqueName],
[Extent1].[UniqueCount] AS [UniqueCount],
CASE WHEN ([Extent2].[AlternateNameId] IS NULL) THEN [Extent1].[Name] ELSE [Extent2].[AlternateName] END AS [C1],
[Extent2].[IsoLanguage] AS [IsoLanguage]
FROM [dbo].[GN_Name] AS [Extent1]
LEFT OUTER JOIN [dbo].[GN_AlternateName] AS [Extent2] ON [Extent1].[GeoNameId] = [Extent2].[GeoNameId]
WHERE (''se'' = [Extent1].[CountryCode]) AND (((''sv'' = [Extent2].[IsoLanguage]) AND ([Extent2].[AlternateName] LIKE @p__linq__0 ESCAPE N''~'')) OR ([Extent1].[Name] LIKE @p__linq__1 ESCAPE N''~''))
) AS [Limit1]',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'ja%',@p__linq__1=N'ja%'
Я не могу понять, что с ним не так, но на это уходит около 5 секунд.
Должен ли я добавить индекс?Может быть, настроить индексированное представление?Мои знания по SQL-серверу ограничены, и я хотел бы вернуться к некоторому реальному кодированию;)
Любые предложения горячо приветствуются!
ОБНОВЛЕНИЕ Я использую SQL Server 2008Следуя инструкциям тайлонра, я получил следующие результаты.
Есть 3 "части", которые составляют 100% от общего количества.Однако я не знаю, как использовать эту статистику.
ОБНОВЛЕНИЕ 2
План выполнения SSMS рекомендовал следующий индекс:
CREATE NONCLUSTERED INDEX IX_GN_Name_CountryCode
ON [dbo].[GN_Name] ([CountryCode])
INCLUDE ([GeoNameId],[Name],[FeatureClass],[FeatureCode],[UniqueName],[UniqueCount])
Я добавил его, и теперь запрос работает намного лучше!
ОБНОВЛЕНИЕ 3 Тайлон предлагает использовать только одно предложение LIKE.Я не уверен, как это сделать.Кто-нибудь готов принять вызов?