LINQtoSQL кеширующий вопрос - PullRequest
       8

LINQtoSQL кеширующий вопрос

1 голос
/ 16 февраля 2010

Я много читал, но не нашел хороших ответов о кешировании LinqToSql ... Думаю, лучший способ задать свой вопрос - просто задать его.

У меня есть скрипт jQuery, вызывающий службу WCF на основе информации, которую скрипт получает из первых двух ячеек каждой строки таблицы. По сути, это цикл по таблице, вызов службы с информацией из ячеек таблицы и обновление строки на основе информации, возвращенной из службы.

Сам сервис выполняет запрос на основе информации от клиента в основном в виде:

Dim b =  From r In db.batches _
                    Where r.TotalDeposit = amount _
                    And r.bDate > startDate AndAlso r.bDate < endDate _
                    Select r

Используя firebug, я заметил, что каждый ответ занимал где-то между 125мс-3сек. Я провел некоторое исследование и наткнулся на статью о кешировании объектов LINQ и применил ее к своему проекту. Я смог вернуть такие вещи, как количество объектов (b.Count) в качестве Ответа на странице, и заметил, что это было кэширование, поэтому я подумал, что готовил с использованием смазки ... однако, когда я попытался выполнить вышеуказанный запрос для кешированный объект, время стало согласованным 700 мс, слишком долго.

Я где-то читал, что LINQ автоматически кэшируется, поэтому я сделал следующее:

    Dim t As New List(Of batch)
    Dim cachedBatch = From d In db.batches _
           Select d
    t = From r In cachedBatch _
                    Where r.TotalDeposit = amount _
                    And r.bDate > startDate AndAlso r.bDate < endDate _
                    Select r
    Return t

Теперь запрос выполняется с постоянным временем ответа 120-140 мс ... что дает ??? Я предполагаю его кэширование, поскольку выполнение запроса к базе данных занимает некоторое время (<35 000 записей). </p>

Мой вопрос, я думаю, должен ли я пытаться кэшировать объекты LINQ? Есть ли хороший способ сделать это, если я не попал в цель?

Как обычно, спасибо !!!

1 Ответ

4 голосов
/ 16 февраля 2010

НЕ ИСПОЛЬЗУЙТЕ код в этой статье. Я не знаю, что этот человек курил, но код в основном читает все содержимое таблицы и помещает его в кэш-память. Я не могу придумать гораздо худший вариант для нетривиальной таблицы (а 35 000 записей определенно нетривиальны).

Linq to SQL не кеширует запросы. Linq to SQL отслеживает определенные объекты , полученные по запросам с использованием их первичных ключей. Это означает, что если вы:

  1. Запрос DataContext для некоторых объектов;
  2. Измените эти сущности (но пока не звоните SubmitChanges);
  3. Запустите другой запрос, который извлекает те же сущности.

Тогда результаты # 3 выше будут теми же сущностями, которые вы извлекли в (1) с изменениями, которые вы внесли в (2) - другими словами, вы получите обратно существующие сущности, которые уже отслеживает Linq, а не старые сущности из базы данных. Но он все равно должен выполнить запрос , чтобы узнать, какие объекты загружать; отслеживание изменений не является оптимизацией производительности.

Если ваш запрос к базе данных занимает более 100 мс, то проблема почти наверняка на стороне базы данных. Вероятно, у вас нет соответствующих индексов для столбцов, по которым вы запрашиваете. Если вы хотите кэшировать вместо решения проблемы перфорирования БД, вам необходимо кэшировать результаты конкретных запросов , что вы должны сделать, указав их в параметрах, использованных для создания запроса. Например (C #):

IEnumerable<Batch> GetBatches(DateTime startDate, DateTime endDate,
    Decimal amount)
{
    string cacheKey = string.Format("GetBatches-{0}-{1}-{2}",
        startDate, endDate, amount);
    IEnumerable<Batch> results = Cache[cacheKey];
    if (results != null)
    {
        return results;
    }
    results = <LINQ QUERY HERE>.ToList();
    Cache.Add(cacheKey, results, ...);
    return results;
}

Это нормально, если результаты нельзя изменить, пока элемент находится в кеше, или если вам не нужны устаревшие результаты. Если это проблема, тогда она станет намного сложнее, и я не буду вдаваться во все тонкости здесь.

Суть в том, что "кэширование" каждой отдельной записи в таблице вообще не кэширует, а превращает эффективную реляционную базу данных (SQL Server) в неаккуратную, неэффективную базу данных в памяти (общий список в кэше) , Не кэшируйте таблицы , кэшируйте запросы , если вам нужно, и прежде чем вы даже решите это сделать, попробуйте решить проблему производительности в самой базе данных.

Для протокола я должен также отметить, что кто-то, кажется, реализовал форму кэширования , основанную на самом IQueryable<T> . Я не тестировал этот метод, и я не уверен, насколько проще было бы использовать его на практике, чем описанное выше (вам все равно придется специально его использовать, он не автоматический), но я перечисляю его как возможная альтернатива.

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