2016-02-02 3 views
7

Я использую .NET framework 4.5.1 Linq to SQL.Один запрос медленнее, чем 3 запроса

У меня есть этот класс продукта, используя код первым:

public class Part 
{ 
    public int PartID { get; set; } 

    [Required(ErrorMessage = "xxx")]   
    public string Title { get; set; } 

    [MaxLength(50)] 
    [Index(IsClustered = false, IsUnique = false,Order =1)] 
    public string Part_Number { get; set; } 

    [MaxLength(50)] 
    [Index(IsClustered = false, IsUnique = false, Order = 2)] 
    public string Manufacturer_Number { get; set; } 
} 

У меня есть около 2500000 этих объектов в базе данных.

Первый подход

var query = db.Parts.Where(s => s.Manufacturer_Number == sstring).ToList();     
query.AddRange(db.Parts.Where(s => s.Part_Number == sstring).ToList()); 
query.AddRange(db.Parts.Where(s => s.Title == sstring).ToList()); 

Второй подход

var query = db.Parts.Where(s => s.Manufacturer_Number == sstring 
|| s.Part_Number == sstring || s.Title == sstring).ToList(); 

Первый подход состоит в 100 раз быстрее, чем во втором подходе. Может кто-нибудь объяснить это?

+8

Вы должны посмотреть на SQL, который был создан вашим linq, а затем проверить план выполнения в вашем ManagmentStudio. Может быть, у вас есть индексы на каждом поле, и простые запросы могут использовать их, но не ваш последний. –

+1

Надеюсь, у него есть индексы, если у вас есть записи на 2,5 миллиона в таблице ... –

+0

Что именно вы хотите достичь ..? –

ответ

1

Сначала без индекса по заголовку Мне немного сложно поверить, что вы получаете поведение, которое вы требуете.

Установите статистику как минимум как минимум и добавьте результаты к этому вопросу.

Но при этом первый подход - это фактически три поездки в базу данных, но будет использовать созданный индекс.

Второй подход - это однократная поездка в базу данных, но, конечно же, это приведет к полному сканированию таблицы, причем 250000 строк, скорее всего, займет нетривиальное количество времени.

+1

Если все поля индексируются, это не приведет к сканированию таблицы. Единственный случай, когда я могу думать о том, где * может * быть реальным различием (т.е. OP не делал временную ошибку), является, если 'sstring' является NULL.Заголовок имеет атрибут «Обязательный», что означает, что он НЕ НЕТ. –

+0

@PanagiotisKanavos Вы уверены, что SQL Server будет использовать несколько индексов в одном запросе? –

+0

SQL Server будет использовать наиболее эффективный вариант. Конечно, это будет, если это * самый дешевый вариант. Или он может решить кэшировать временные результаты в tempdb. Плохая статистика или недостающие индексы, однако, означает, что он может выбрать неправильный план, потому что он не знал, какие данные он найдет в 'Title'. В любом случае два подхода не эквивалентны - первый подход * будет * возвращать несколько раз строк, которые выполняют более одного условия. Второй подход будет фильтровать строки по всем условиям и возвращать их один раз. –

1

Как я говорю проблема может быть в индексах, если вы хотите, чтобы ваш запрос идти быстрее с этим точным запросом я предлагаю вам создать этот индекс:

CREATE NONCLUSTERED INDEX PartIndex 
ON Part (PartID, Manufacturer_Number, Part_Number, Title) 

Не забудьте обновить статистику, если вы измените таблицу данных много.

+2

Номер_объекта и Номер_Интерфейса уже проиндексированы. Свойства имеют атрибут «Index». Это свойство 'Title', которое не имеет индекса. Из-за этого можно было бы ожидать обеих попыток добиться примерно того же времени. OP должен опубликовать сгенерированные запросы –

+0

@PanagiotisKanavos согласен, давайте подождем его –

+0

Полезно, SQL Server отслеживает, какие индексы вы * не * имеете, и что бы изменило ситуацию. Вот несколько сценариев, которые расскажут вам, какие индексы вы можете добавить, что даст лучшие улучшения производительности: http://mikesknowledgebase.com/pages/SQLServer/FindingMissingIndexes.htm –