Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Производительность базы данных — это обширная и сложная тема, охватывающая весь стек компонентов: база данных, сеть, драйвер базы данных и уровни доступа к данным, такие как EF Core. Хотя высокоуровневые слои и RM, такие как EF Core, значительно упрощают разработку приложений и повышают удобство обслуживания, иногда они могут быть непрозрачными, скрывая критически важные для производительности внутренние сведения, такие как выполнение SQL. В этом разделе показано, как добиться хорошей производительности с помощью EF Core и как избежать распространенных ошибок, которые могут снизить производительность приложения.
Определите узкие места и измеряйте, измеряйте, измеряйте
Как и всегда с производительностью, важно не спешить с оптимизацией без данных, показывающих проблему; как сказал великий Дональд Кнут, "Преждевременная оптимизация — корень всех бед". В разделе диагностики производительности рассматриваются различные способы понять, где ваше приложение тратит время в логике базы данных и как определить конкретные проблемные области. После выявления медленного запроса можно рассмотреть решения: отсутствует ли у базы данных индекс? Следует ли попробовать другие шаблоны запросов?
Всегда тестируйте код и возможные варианты самостоятельно. Раздел диагностики производительности содержит пример теста с помощью BenchmarkDotNet, который можно использовать в качестве шаблона для собственных тестов. Не предполагайте, что общие общедоступные тесты применяются as-is к конкретному варианту использования; Различные факторы, такие как задержка базы данных, сложность запросов и фактические объемы данных в таблицах, могут иметь глубокое влияние на то, какое решение лучше всего подходит. Например, многие общедоступные тесты выполняются в идеальных условиях сети, где задержка в базе данных почти нулевая, и с очень легкими запросами, которые вряд ли требуют обработки (или дискового ввода-вывода) на стороне базы данных. Хотя это полезно для сравнения накладных расходов среды выполнения различных слоев доступа к данным, различия, которые они показывают, как правило, являются незначительными в реальном приложении, где база данных выполняет фактическую работу, а задержка в взаимодействии с базой данных является важным фактором производительности.
Аспекты производительности доступа к данным
Общая производительность доступа к данным может быть разделена на следующие широкие категории:
- Чистая производительность базы данных. С реляционной базой данных EF преобразует запросы LINQ приложения в инструкции SQL, выполняемые базой данных; эти инструкции SQL могут выполняться более или менее эффективно. Правильный индекс в правильном месте может повлиять на производительность SQL или перезапись запроса LINQ может привести к созданию более эффективного SQL-запроса EF.
- Передача сетевых данных. Как и в любой сетевой системе, важно ограничить объем данных, передаваемых по сети. Это включает в себя то, что вы отправляете и загружаете только те данные, которые действительно понадобятся, а также избегаете так называемого "декартового взрыва" при загрузке связанных сущностей.
- Круглые обходы сети. Помимо объема данных, передаваемых туда и обратно, сетевые раунды, поскольку время, затраченное на выполнение запроса в базе данных, может значительно уступать времени, которое пакеты тратят на путь между вашим приложением и вашей базой данных. Затраты на взаимодействие в значительной степени зависят от вашей среды; чем дальше находится сервер базы данных, тем выше латентность и дороже каждый запрос. С появлением облака приложения все чаще находятся в стороне от базы данных и "чат" приложений, которые выполняют слишком много циклов, что снижает производительность. Поэтому важно точно понимать, когда приложение обращается к базе данных, сколько раз оно совершает обмен данными, и можно ли свести это число к минимуму.
- Издержки среды выполнения EF. Наконец, сам EF добавляет некоторые затраты времени на выполнение операций с базой данных: EF необходимо скомпилировать ваши запросы из LINQ в SQL (хотя это обычно делается только один раз), отслеживание изменений добавляет некоторые издержки (но может быть отключено) и т. д. На практике затраты времени, добавляемые EF для реальных приложений, скорее всего, будут незначительными в большинстве случаев, так как время выполнения запросов в базе данных и задержка сети доминируют над общим временем; но важно понять, какие у вас есть варианты и как избежать некоторых ошибок.
Знать, что происходит под капотом
EF позволяет разработчикам сосредоточиться на бизнес-логике путем создания SQL, материализации результатов и выполнения других задач. Как и любой слой или абстракция, он также, как правило, скрывает то, что происходит под капотом, например, фактические выполняемые запросы SQL. Производительность не обязательно является критическим аспектом каждого приложения, но в приложениях, где это так, важно, чтобы разработчик понимал, что EF делает для них: проверьте исходящие sql-запросы, следуйте круглым запросам, чтобы убедиться, что проблема N+1 не возникает, и т. д.
Кэш за пределами базы данных
Наконец, наиболее эффективным способом взаимодействия с базой данных является то, чтобы не взаимодействовать с ней вообще. Другими словами, если доступ к базе данных отображается в качестве узких мест производительности в приложении, может потребоваться кэшировать определенные результаты за пределами базы данных, чтобы свести к минимуму запросы. Хотя кэширование добавляет сложность, это особенно важная часть любого масштабируемого приложения: хотя уровень приложений можно легко масштабировать, добавив дополнительные серверы для обработки повышенной нагрузки, масштабирование уровня базы данных обычно гораздо сложнее.