Сравнение производительности LINQ to SQL - PullRequest
3 голосов
/ 10 ноября 2010

У меня проблема с запросом linq to sql - с точки зрения производительности.То, что я пытаюсь сделать, это выяснить, соответствуют ли элементы моей коллекции из примерно 500 предметов (в списке) записи в БД.В настоящее время эта операция занимает около 300 секунд!База данных содержит более миллиона строк, и в будущем она будет расти, поэтому столь ранний уровень производительности просто недопустим.Пример ниже:

var query = from item in db.DataTable.Where(x => x.date == suppliedDate)
            where inputList.Contains(item.name)
            select new { item.name};

Помощь!

edit: Большое спасибо за все ваши предложения!я просто хотел добавить несколько дополнительных наблюдений, поскольку теперь я могу просматривать вывод SQL моего запроса LINQ (см. ниже)

SELECT [t0].[name]
FROM [dw].[DataTable] AS [t0]
WHERE ([t0].[name] IN (@p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11, @p12, @p13, @p14, @p15, @p16, @p17)) AND ([t0].[date] = @p18)
-- @p0: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [Mark]
-- @p1: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [Owen]
-- @p2: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [James]
-- @p3: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [John]

и т. д.

Это делает500 отдельных попаданий на БД?(Как предположил Ян)?и есть ли способ улучшить производительность, не прибегая к хранимым процедурам и не создавая дополнительную таблицу?(оба варианта на самом деле не доступны для меня прямо сейчас).Я попробовал предложение Джеффа, и это увеличило мое время выполнения с 300 до 126 секунд, но это все еще очень много, особенно учитывая, что объединение БД займет не более 10 секунд.

Большое спасибо

Ответы [ 5 ]

2 голосов
/ 10 ноября 2010
-- @p0: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [Mark] 

Является ли столбец varchar?

Если вы проверите план выполнения для этого запроса, вы можете увидеть, что сервер sql преобразует весь индекс в nvarchar (DOOOOOM!)

Исправлениеэто преобразование параметров в varchar.


Вы можете получить команду и сбросить типы параметров непосредственно на ней (в вашем случае ANSI-строку).

http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.getcommand.aspx http://msdn.microsoft.com/en-us/library/system.data.dbtype.aspx

Затем вы можете вызвать ExecuteReader для этой команды, получив DbDataReader.Вы можете передать этот DbDataReader методу Translate вашего datacontext, и он даст вам IEnumerable<T>, что вы ожидаете от linq.

http://msdn.microsoft.com/en-us/library/bb534213.aspx

Я опубликовалкод для этого здесь

2 голосов
/ 10 ноября 2010

Вы можете делать 500 отдельных запросов к базе данных, которые с этим запросом!

Сначала посмотрите на sql, запущенный с использованием профилировщика запросов на сервере SQL, и посмотрите, выполняет ли Linq-to-sql то, что вы ожидаете.

2 голосов
/ 10 ноября 2010

Попробуйте

var query = from item in db.DataTable
            where item.date == suppliedDate
            where inputList.Contains(item.name)
            select new { item.name};

Вы можете использовать LinqPad для проверки вашего запроса, и он также покажет вам, что генерируется SQL.

1 голос
/ 10 ноября 2010

Более быстрый способ - избежать кода linq, вы можете сохранить имена inputList в таблицу sql (используя вставку xml), а затем написать хранимую процедуру, которая выполняет выборку и возвращает набор данных. Затем в linq вы можете вызвать этот sp и извлечь результат.

1 голос
/ 10 ноября 2010

Подобные вещи будут выполняться немного быстрее в базе данных, учитывая количество записей, с которыми вы имеете дело.

Я бы массово вставлял элементы из вашего списка во временную таблицу, а затем выполнял внутреннее соединение или пересекался / за исключением случаев, когда необходимо получить результат.

MSSQL 2008 также имеет очень быстрый оператор MERGE sql, который тоже может помочь. Выполнение чего-либо подобного с более чем миллиардом записей занимает несколько миллисекунд, если ваше оборудование может справиться.

Что подводит меня к другому аппаратному обеспечению :). Не недооценивайте требования к оборудованию, особенно скорость жесткого диска (как правило, массив RAID 5/6, состоящий из 6/12 шпинделей). Для данных, с которыми вы имеете дело, если вам нужна действительно хорошая производительность ваших очередей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...