2009-08-18 7 views
20

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

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

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

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

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

+0

Я думаю, что dataContext.table_sample.Where (e => e.x == 1) .Take (100) проще читать mantain. И SampleTable кажется приятнее, чем table_sample. –

+0

В конструкторе DataClassesDataContext (.dbml) вы также можете указать, какие столбцы извлекаются. По умолчанию все столбцы извлекаются (SELECT * в SQL). Просто нажмите на поле и просмотрите его свойства, чтобы изменить его. –

ответ

25

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

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

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

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

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

+0

Tks, код был исправлен. – Zanoni

+1

Не совсем это не было - я думаю, вы имеете в виду «где e.x == 1» –

+0

Вы правы, исправлены. – Zanoni

2

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

2

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

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

  • в вашем «где» положение должно быть, вероятно х == 1 не х = 1 (сравнение вместо присваивания)
  • «select e» вернет все столбцы, где вам, вероятно, понадобятся только некоторые из них - точнее с предложением select (введите только требуемые столбцы); «Выберите *» является Vaste ресурсов
  • убедитесь, ваша база данных хорошо индексируются и попытаться использовать индексированных данных

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

1

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

2

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

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

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

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

    dbContext.Log = Console.Out;

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