LINQ to SQL Query Optimization - PullRequest
       3

LINQ to SQL Query Optimization

0 голосов
/ 29 августа 2011

Работал в основном над Java и новичком в LINQ, поэтому мне нужно несколько советов относительно производительности этого запроса. У меня есть 3 таблицы

1. Products  -->                   ProductID | Name | Price | VendorID
2. Category  -->                   CategoryID | Label
3. SubCategory-->                  SubCategoryID | Label | ParentID
4. Product_SubCategory_Mapping-->  ProductID | SubCategoryID 
5. Vendor     -->                  VendorID | VendorName

Я хочу выбрать все продукты из таблицы продуктов вместе с их поставщиками для любой подкатегории. Должен ли следующий запрос работать нормально? Или нужна какая-то оптимизация?

var list =  (from p in Products 
             join cat in Product_SubCategory_Mapping 
             on p.UserId equals cat.UserId 
             join sub in SubCategories 
             on cat.SubCategoryId equals sub.SubCategoryId
             where sub.CategoryId == 19 && CustomFunction(p.ID) > 100 
             select new { p, p.Vendor, trend = CustomFunction(p.ID) })
             .Skip((pageNum - 1) * pageSize)
             .Take(pageSize);

Я буду создавать собственный класс, который будет соответствовать результату запроса.

  1. Является ли создание представления / хранимой процедуры лучшим сценарием в этом случае?
  2. Можно ли назвать CustomFunction (p.ID)> 100, чтобы функция не вызывалась дважды? Это пользовательская функция в базе данных.
  3. Для пейджинга будет ли Skip and take работать хорошо?

Ответы [ 2 ]

3 голосов
/ 29 августа 2011

Вы на правильном пути, но LINQ to SQL не поймет CustomFunction(), поэтому вам нужно переключиться на LINQ to Objects с AsEnumerable(), прежде чем вы сможете его вызвать. Вы также можете использовать let для захвата результата CustomFunction() один раз для использования в другом месте запроса:

var listFromSql = from p in Products
                  join cat in Product_SubCategory_Mapping
                    on p.UserId equals cat.UserId
                  join sub in SubCategories
                    on cat.SubCategoryId equals sub.SubCategoryId
                  where sub.CategoryId == 19
                  select p;

var list = from p in listFromSql.AsEnumerable()
           let trend = CustomFunction(p.ID)
           where trend > 100
           select new { p, p.Vendor, trend };

Обновление: Чтобы ответить на перечисленные вопросы:

  1. Это относительно простой SQL, поэтому то, что генерирует L2SQL, должно быть в порядке. Вы можете использовать L2SQL logging или SQL Profiler, чтобы подтвердить, что SQL достаточно хорош.
  2. См. let выше.
  3. Skip() и Take() на IQueryable<> (как listFromSql выше) преобразуются в соответствующий SQL, ограничивая набор результатов, передаваемых по проводам. Skip() и Take() в IEnumerable<> просто перечисляют последовательность, чтобы получить запрошенные результаты, но работают с полным набором результатов, возвращаемым из SQL.
1 голос
/ 29 августа 2011

Так как CustomFunction является ScalarFunction в базе данных, LINQ to SQL должен быть в состоянии эффективно ее оценить.Возможно, вы захотите использовать LET, чтобы получить значение один раз, но проверьте сгенерированный SQL и план выполнения запроса, чтобы увидеть, предлагает ли он какие-либо улучшения или же SQL Server автоматически выполняет соответствующие оптимизации внутри.

var list =  (from p in Products  
             join cat in Product_SubCategory_Mapping  
             on p.UserId equals cat.UserId  
             join sub in SubCategories  
             on cat.SubCategoryId equals sub.SubCategoryId
             let trend = CustomFunction(p.ID) 
             where sub.CategoryId == 19 && trend > 100  
             select new { p, p.Vendor, trend }) 
             .Skip((pageNum - 1) * pageSize) 
             .Take(pageSize); 

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

var list = (from p in Products
           from cat in p.Product_SubCategory_Mappings
           let trend = CustomFunction(p.ID)
           where cat.SubCategory.CategoryId == 19 && trend > 100
           select new { Product = p, p.Vendor, trend})
           .Skip(pageNum - 1) * pageSize)
           .Take(pageSize);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...