Подтвердить что ты не робот

Выбор первых 100 записей с использованием Linq

Как я могу вернуть первые 100 записей с помощью Linq?

У меня есть таблица с 40 миллионами записей.

Этот код работает, но он медленный, потому что будет возвращать все значения перед фильтром:

var values = (from e in dataContext.table_sample
              where e.x == 1
              select e)
             .Take(100);

Есть ли способ вернуть фильтр? Как предложение T-SQL TOP?

4b9b3361

Ответ 1

Нет, это не возвращает все значения перед фильтрацией. Take(100) в конечном итоге будет частью отправленного SQL - возможно, с помощью TOP.

Конечно, имеет смысл сделать это, когда вы указали предложение orderby.

LINQ не выполняет запрос, когда он достигает конца вашего выражения запроса. Он отправляет только любой SQL, когда вы вызываете оператор агрегации (например, Count или Any), или вы начинаете повторять результаты. Даже вызов Take на самом деле не выполняет запрос - возможно, вы захотите впоследствии добавить к нему дополнительную фильтрацию, например, которая может оказаться частью запроса.

При запуске повторения результатов (обычно с foreach) - это когда SQL действительно будет отправлен в базу данных.

(Я думаю, что ваше предложение where немного сломано, кстати. Если у вас проблемы с вашим реальным кодом, это поможет увидеть максимально приближенный к реальности код.)

Ответ 2

Я не думаю, что вы правы в этом, возвращая все записи, прежде чем принимать 100 лучших. Я думаю, что Linq решает, какая строка SQL будет в момент выполнения запроса (aka Lazy Loading), и ваша база данных сервер будет оптимизировать его.

Ответ 3

Вы сравнили стандартный SQL-запрос с вашим запросом linq? Какой из них быстрее и насколько значительна разница?

Я согласен с вышеприведенными комментариями в том, что ваш запрос linq обычно правильный, но...

  • в предложении 'where' должно быть x == 1 не x = 1 (сравнение вместо назначения)
  • 'select e' вернет все столбцы, где вам, вероятно, понадобятся только некоторые из них, - точнее с предложением select (введите только требуемые столбцы); "select *" - это ресурс ресурсов.
  • убедитесь, что ваша база данных хорошо проиндексирована и попытается использовать индексированные данные.

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

Ответ 4

Я согласен с Джоном Скитом, но просто хотел добавить:

  • Сгенерированный SQL будет использовать TOP для реализации Take().

  • Если вы можете запустить SQL-Profiler и выполнить свой код в режиме отладки, вы сможете точно увидеть, что такое SQL, и когда он будет выполнен. Если вы найдете время для этого, вы узнаете многое о том, что происходит под ним.

  • Существует также свойство DataContext.Log, которое вы можете назначить TextWriter для просмотра сгенерированного SQL, например:

    dbContext.Log = Console.Out;

  • Другой вариант - поэкспериментировать с LINQPad. LINQPad позволяет подключиться к источнику данных и легко попробовать различные выражения LINQ. На панели результатов вы можете переключиться на то, чтобы SQL генерировал выражение LINQ.

Ответ 5

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