Почему был бы, снова используя DataContext оказать отрицательное влияние производительности?

После ясно сумма из исследование и некоторых ошибок, я изменил свой код так, чтобы он создал новый DataContext каждый раз, когда база данных запрашивается, или данные вставляются. И база данных часто запрашивается - для каждой из 250k транзакций, которые обрабатываются, база данных запрашивается для получения идентификатора клиента, идентификатора отдела и категории, прежде чем транзакция будет вставлена.

Так же теперь я пытаюсь оптимизировать код, как он только обрабатывал приблизительно 15 транзакций в секунду. Я удалил некоторые посторонние запросы и добавил некоторые индексы и получил его до 30/секунд. Я затем полагал, что даже при том, что все говорят, что DataContext легок, это получено для стоения чего-то для создания нового 4 раза на транзакцию, таким образом, я пытался снова использовать DataContext. Я нашел, к моему большому удивлению, что многократное использование контекста заставило производительность ухудшаться к 10 транзакциям в секунду!

Почему это имело бы место? Это, потому что DataContext кэширует объекты в памяти и сначала перерывает ее список в оперативной памяти прежде, чем запросить базу данных? Так, чтобы, если, например, я ищу идентификатор клиента (первичный ключ) для клиента с именем 'MCS' и столбец имени клиента, имел кластерный индекс на нем так, чтобы запрос базы данных был быстр, поиск в оперативной памяти будет медленнее?

И действительно ли это верно, что создание/расположение такого количества соединений дб могло замедлить вещи или является этим просто другая преждевременная оптимизация? И если это верно, там способ снова использовать DataContext, но иметь его, выполняют фактический запрос базы данных для каждого linq к запросу SQL?

14
задан Community 23 May 2017 в 12:09
поделиться

4 ответа

Вот почему повторное использование DataContext не является лучшей практикой, из Документация MSDN DataContext :

DataContext является источником всех объекты, отображаемые в базе данных связь. Он отслеживает изменения, которые вы сделано для всех извлеченных объектов и поддерживает "кэш идентичности", который гарантирует, что извлеченные объекты более одного раза представлены используя тот же экземпляр объекта.

Обычно экземпляр DataContext рассчитан на одну "единицу" работать ", но ваше приложение определяет этот термин. DataContext - это легкий и недорогой в Создайте. Типичный LINQ to SQL приложение создает DataContext экземпляры в области метода или как член недолговечных классов, которые представляют собой логический набор связанных операции с базой данных.

Если вы повторно используете DataContext для большого количества запросов, ваша производительность снизится по двум возможным причинам:

  1. Если кэш идентификаторов DataContext в памяти станет настолько большим, что ему придется начать запись в файла подкачки, тогда ваша производительность будет привязана к скорости считывающей головки HD, и, по сути, вообще не будет причин для использования кеша.

  2. Чем больше объектов идентификации находится в памяти, тем дольше длится каждая операция сохранения.

По сути, то, что вы делаете, нарушает принцип UoW для класса DataContext.

Открытие соединений с базой данных действительно связано с некоторыми накладными расходами, но сохранение соединения открытым в течение длительного периода времени (что часто также означает блокировку таблицы) менее предпочтительно, чем их быстрое открытие и закрытие.

Еще одна ссылка из MSDN, которая может вам помочь, а может и не помочь:

Как: повторно использовать соединение между командой ADO.NET и контекстом данных (LINQ to SQL)

15
ответ дан 1 December 2019 в 13:32
поделиться

Вам нужно будет профилировать все от начала до конца и посмотреть, где на самом деле вы тратите время.

Кластеризованный индекс не обязательно самый быстрый, если строка широкая. Самым быстрым, вероятно, будет покрывающий некластеризованный индекс, но на самом деле это не относится к делу.

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

1
ответ дан 1 December 2019 в 13:32
поделиться

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

Я предполагаю, что ухудшение связано с обработкой DataContext объектов, которые он отслеживает: повторное использование контекста будет постоянно увеличивать количество отслеживаемых объектов, а вызов SaveChanges может в конечном итоге потребовать больше времени .

Опять же, это предположение - но я бы начал искать именно здесь.

1
ответ дан 1 December 2019 в 13:32
поделиться

Не совсем по теме, но не рассматривали ли вы возможность создания кэша на уровне приложения для поиска идентификатора клиента, идентификатора отдела и категории? Из вашего сообщения неясно, сколько таких сущностей существует в вашей системе и что нужно сделать, чтобы получить их с помощью запроса.

Однако, в качестве примера, если в вашей системе миллион категорий, и вам нужно найти их Id по названию категории, то постоянное хранение словаря имен/Id в памяти для поиска позволит вам сэкономить на обращении к базе данных при обработке транзакции. Это может значительно повысить производительность (это предполагает несколько вещей, например, что новые категории не добавляются регулярно). Как правило, обращения к базе данных обходятся дороже, чем операции в памяти.

1
ответ дан 1 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: