#c# #sql #linq-to-sql #windows-phone-7
#c# #sql #linq-to-sql #windows-phone-7
Вопрос:
У меня проблема с производительностью Linq to SQL в Windows Phone 7, но я действительно не уверен, что я делаю неправильно (у меня почти нет опыта работы с Linq to SQL, и чем больше я читаю, тем больше я запутываюсь). вздох).
Предыстория
У меня есть локальная база данных SQL CE с пятью таблицами, по два столбца в каждой ( int
первичный ключ и nvarchar
значение, плюс индексы) и около 100 000 записей в каждой таблице. Размер базы данных составляет около 20 МБ и реализован в соответствии с рекомендациями в собственном примере локальной базы данных Microsoft MVVM.
Проблема
После упрощения, насколько я могу, у меня есть запрос в моей модели представления, который выглядит следующим образом:
var query =
(
from t1 in db.table1
join t2 in db.table2 on t1.id equals t2.id
join t3 in db.table3 on t1.id equals t3.id
join t4 in db.table4 on t1.id equals t4.id
join t5 in db.table5 on t1.id equals t5.id
where
SqlMethods.Like(t5.value, "%" searchTerm "%")
select new Results
{
Field1 = t1.value,
Field2 = t2.value,
Field3 = t3.value,
Field4 = t4.value,
Field5 = t5.value,
}
).Take(100);
SearchResults = new ObservableCollection<Results>(query);
Это приводит к следующему SQL:
SELECT TOP (100)
[t0].[value] AS [Field1],
[t1].[value] AS [Field2],
[t2].[value] AS [Field3],
[t3].[value] AS [Field4],
[t4].[value] AS [Field5]
FROM
[table1] AS [t0],
[table2] AS [t1],
[table3] AS [t2],
[table4] AS [t3],
[table5] AS [t4]
WHERE ([t4].[value] LIKE @p0)
AND ([t0].[id] = [t4].[id])
AND ([t0].[id] = [t3].[id])
AND ([t0].[id] = [t2].[id])
AND ([t0].[id] = [t1].[id])
Проблема в том, что когда поисковый запрос очень специфичен (только один результат), в среднем на выполнение уходит около 5 секунд. Это до того, как я добавлю какие-либо другие требования, такие как несколько предложений where, ранжирование, упорядочение и т.д. Даже если я ищу то, что, как я знаю, является первой строкой в базе данных, это все равно занимает около 5 секунд.
Если я изменю подход и буду искать что-то очень распространенное (например, «the»), для выполнения потребуется всего около 100 мс. Я знаю Like
, что использование подстановочных знаков сложнее, чем прямое ==
сравнение, но я не знаю, почему производительность так отличается.
(Я знаю, что это бесполезное сравнение, поскольку это яблоки и апельсины, но я ранее выполнял аналогичные запросы в той же базе данных, написанной на MySQL, и они неизменно получали результаты примерно за 0,3-0,4 с, независимо от того, что я искал).
Я упускаю что-то действительно очевидное? Я следил за примерами Microsoft и читал много руководств в Интернете, но я не могу найти причину, по которой этот запрос выполняется так медленно. Заранее большое спасибо за любые советы, которые вы можете предложить.
Комментарии:
1. Я бы настоятельно рекомендовал вам попробовать выполнить тот же запрос без использования LINQ. Я подозреваю , что вы увидите ту же производительность, что означает, что виноват вовсе не LINQ. Имейте в виду, что при таком поиске по шаблону база данных в принципе не может использовать какие-либо индексы, тогда как при прямом равенстве она должна быть в состоянии очень быстро добраться до нужной записи.
2. Спасибо за быстрый ответ, Джон. Вы правы, я только что профилировал ту же базу данных на своем рабочем столе, используя сгенерированный SQL, и получил аналогичный коэффициент производительности (1,2 с для конкретного запроса против 0,02 с для общего запроса). Я не думал, что подстановочные знаки будут иметь такое большое снижение производительности.
Ответ №1:
ПРОСТОЙ ЗДРАВЫЙ СМЫСЛ.
- Вы запускаете это на телефоне с низким энергопотреблением и выполняете запрос сканирования таблицы.
Методы sqlmethod.Например (t5.value, «%» searchTerm «%»)
означает отсутствие захвата индекса, это сканирование таблицы.
).Возьмите (100);
Означает: остановка после нахождения 100 элементов.
Теперь, с очень распространенным словом («the») это может означать, что обрабатывается только 100 элементов. С более необычным словом может потребоваться выполнить половину таблицы, чтобы получить 100 элементов. Сканирование таблицы в половину этой базы данных займет время. Simlpe.
В общем, sql плохо подготовлен для синтаксического анализа слов в текстах — вот почему real sql server ahs полнотекстовая индексация. Запуск этого (% word%) на оборудовании с низким pwoer (wp7 = естественно, происходит медленно.
Здесь нет абсолютно ничего, что указывало бы на то, что LINQ является проблемой. LINQ преобразует это, вероятно, в довольно эффективный SQL-запрос в пределах границ перфорации, которые вы определяете в запросе — к сожалению, это худшее, что вы можете сделать с базой данных.
Комментарии:
1. Спасибо, Том, я думаю, что мой здравый смысл иссякает после того, как я так долго смотрел на это! Ваше объяснение очень четкое, я думаю, я просто подумал (надеялся?) в этом каким-то образом виновато мое непонимание Linq. Я думаю, мне нужно переформулировать мой запрос и / или данные, чтобы избежать такой ситуации с подстановочными знаками, но я борюсь. В любом случае, спасибо за ваше время и указание на то, что должно быть очевидным 🙂