Слишком много данных в Contains (Linq): как увеличить производительность

#c# #asp.net #sql-server #linq

#c# #asp.net #sql-сервер #linq

Вопрос:

У меня есть запрос linq, подобный этому:

 from a in context.table_A
   join b in
   (from temp in context.table_B
   where idlist.Contains(temp.id)
   select temp)
   on a.seq_id equals b.seq_id into c
   where
   idlist.Contains(a.id)
   select new MyObject
   {
     ...
   }).ToList();
  
  • idlist — это список
  • Проблема, с которой я сталкиваюсь, заключается в том, что idlist имеет слишком много значений (от сотен тысяч до нескольких миллионов записей). Он отлично работает с небольшим количеством записей, но когда записей слишком много, функция contains выдает ошибку.

Журнал ошибок

План запроса не может быть создан из-за нехватки внутренних ресурсов процессора запросов. Это редкое событие и происходит только для очень сложных запросов или запросов, которые ссылаются на очень большое количество таблиц или разделов. Упростите запрос.

Я хочу улучшить производительность этого раздела. Есть идеи?

Комментарии:

1. Попробуйте проверять пакетами.

2. в чем проблема idlist ?

3. idlist является параметром этой функции

4. Можете ли вы отменить запрос и присоединиться к idList, а не к нему? В качестве альтернативы реструктурируйте свои данные так, чтобы ваши ссылки можно было искать в одном запросе.

Ответ №1:

Я бы посоветовал установить расширение linq2db.EntityFrameworkCore и использовать временные таблицы с быстрым BulkCopy

 public class IdItem
{
   public int Id { get; set; }
}

...

var items = idList.Select(id => new IdItem { Id = id });

using var db = context.CreateLinqToDBConnection();
using var temp = db.CreateTempTable("#IdList", items);

var query =
   from a in context.table_A
   join id1 in temp on a.Id equals id1.Id
   join b in context.table_B on a.seq_id equals b.seq_id
   join id2 in temp on b.Id equals id2.Id
   select new MyObject
   {
      ...
   };

// switch to alternative translator
var query = query.ToLinqToDB();

var result = query.ToList();