Производительность запуска Entity Framework 6 в среде / сценарии SaaS - PullRequest
0 голосов
/ 16 апреля 2019

Мы используем EF6.2 в нашем веб-приложении SaaS. У нас есть база данных для каждой учетной записи, поэтому каждый клиент получает отдельную базу данных SQL Server.

То, что мы видим, это крайне медленные стартапы. Мы также видим, что стартапы становятся пропорционально медленнее с количеством добавляемых нами аккаунтов .

В настоящее время мы не используем ни одну из возможных оптимизаций. Мы не делаем ngen, мы не «предварительно компилируем» представления. Но что меня беспокоит, так это то, что мы берем не общее снижение производительности, а по каждому аккаунту.

Это заставляет меня поверить, что это связано с кешем метаданных, который, согласно статье, встроен в память и помечен хешем, полученным из строки соединения. https://docs.microsoft.com/en-us/ef/ef6/fundamentals/performance/perf-whitepaper

3.4.1 Алгоритм кэширования метаданных

1.Метаданные для модели хранятся в ItemCollection для каждого EntityConnection. • Как примечание, есть разные ItemCollection объектов для разных частей модели. Например, StoreItemCollections содержит информацию о базе данных модель; ObjectItemCollection содержит информацию о модели данных; EdmItemCollection содержит информацию о концептуальной модели.

2. Если два соединения используют одну и ту же строку соединения, они будут использовать один и тот же экземпляр ItemCollection .

Ищет какие-либо предложения о том, как сократить время "разогрева" до единичного случая

РЕДАКТИРОВАТЬ: это БД на основе EDMX для модели, без миграций

1 Ответ

0 голосов
/ 16 апреля 2019

Каждый контекст БД будет стоить единовременное ускорение при первом обращении к нему, поэтому вам нужно будет убедиться, что клиентское соединение касается только своего собственного DbContext, чтобы избежать первого ожидания ускорения на всех клиентских БД. Контекст затрагивается. Для моей модели у меня есть общая база данных, которая используется при первоначальном входе в систему для определения того, с какой версионной базой данных должен общаться клиент, после чего аутентифицированный пользователь передается в свою базу данных. Последнее, что вам нужно, это код, который перебирает DbContexts любым способом.

Редактировать: вышеприведенное неверно, проверено тестом. Экземпляры DbContext для одной и той же схемы, попадающие в разные экземпляры базы данных в одном и том же домене приложения, не требуют дополнительных затрат. Ключевым фактором для веб-приложения является то, как домен приложения находится в области запроса. (с учетом любого распределения нагрузки и т. д.)

Другим важным фактором является использование DB-First и установка инициализатора базы данных на #null, чтобы избежать любых проверок миграции и т. Д. Это сэкономит время раскрутки.

Вы можете использовать ограниченный контекст для обслуживания ключевых областей вашего приложения. Чем больше и сложнее определение контекста, тем дольше длится раскрутка. Используя ограниченные контексты для покрытия тесно связанных областей приложения, вы можете сократить время, необходимое для раскрутки данного контекста при первом использовании. Например, OrderManagementContext, CustomerManagementContext. На объекты можно ссылаться в каждом контексте, но вы можете оптимизировать определения, где вам нужно только сводное представление в контексте, который не обрабатывает эту сущность на верхнем уровне. Например, когда я работаю с заказами, мне нужно резюме клиента. Вместо того чтобы отображать весь Customer и связанные с ним объекты, которые меня не интересуют, OrderDbContext отображает сущность OrderCustomer, которая отображает только поля из таблицы Customers (или представления) для полей, которые мне нужны о клиенте при работе с заказами. , Меньше, меньше, проще сущностей в каждом контексте = более быстрый контекст инициализации.

Наконец, когда пользователь заходит в систему, раскрутите контекст (ы) на ранних этапах процесса входа в систему, выполнив простой запрос к одному объекту в контексте. Это запускает первоначальное однократное ускорение для сопоставления, и таким образом первый «реальный» запрос не будет обработан с такой задержкой. То есть

using (var orderContext = new OrdersDbContext())
{
   var result = orderContext.Orders.Any();
}
using (var customerContext = new CustomersDbContext())
{
   var result = customerContext.Customers.Any();
}

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

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

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