#sql-server #entity-framework #ado.net #load-balancing #database-administration
#sql-сервер #entity-framework #ado.net #балансировка нагрузки #администрирование базы данных
Вопрос:
У меня проблема с моей базой данных (Microsoft SQL Server), у нас много пользователей, использующих наш API, и этот API делает много запросов к нашей базе данных (это нормально, потому что мы сохраняем данные отслеживания), мы используем балансировщик нагрузки для нашего API, поэтому мы можем обрабатывать многозапросов, но это дало нам проблему, которая заключается в том, что утром все работает нормально, но когда день проходит, все идет очень медленно, я просмотрел монитор активности (я не администратор базы данных, но у команды его нет), и я заметил, что, когда он идет медленно, ожидающие задачи выполняются медленно.увеличение, оно всегда больше 500 (ожидающие задачи всегда около 500-800), в результате этого я поговорил со своим менеджером, что также не является техническим, и мы арендовали сервер, на котором будет работать только база данных, это спецификации:
Спецификации сервера:
- 128 ram, 16 vcpu
Но проблема та же:
Я посмотрел на диспетчер задач и заметил, что он даже не использует 100% оперативной памяти или процессора:
поэтому я хочу, чтобы эксперт мог порекомендовать мне, что делать, потому что у меня есть оборудование, и оно не улучшается:(, заранее спасибо.
Некоторая соответствующая информация:
-
Наш API использует entity Framework, я слышал, что с помощью ADO.NET можно ли это улучшить, правда ли это?
-
Покупка критически важного для бизнеса уровня базы данных SQL Azure может решить нашу проблему?
-
У нас есть de SQL Standard edition
-
Свойства ЭКЗЕМПЛЯРА SQL:
Ответ №1:
Недавно я столкнулся с этой проблемой на сервере sql. Пожалуйста, найдите конфликт блокировок в Google. Ваша база данных выполняет свою работу и нуждается в блокировке для выполнения обновлений и вставок. Это необходимо для поддержания согласованности данных. Это компромисс между согласованностью и скоростью (= параллелизм). Вам нужно взглянуть на уровень приложений и попытаться сократить ваши транзакции. Вы также должны посмотреть на уровень изоляции транзакций. Сериализуемый не всегда нужен и является плохим выбором, когда много блокировок. Пожалуйста, найдите уровни изоляции и как их выбрать. Возможно, вам следует поговорить со своими разработчиками о READ_COMMITTED_SNAPSHOT. Если вы думаете о read_commited_snapshot, взгляните на использование tempdb, которое станет выше. Это легче сказать, чем сделать. Я знаю. Если вы сможете снять блокировки, ваш сервер автоматически станет быстрее. Вот почему вы не видите интенсивного использования процессора и оперативной памяти. Большую часть времени он ждет. Оптимизируйте свои транзакции.
Попробуйте создать базовый уровень производительности перед внесением изменений, чтобы вы могли измерить, имеют ли изменения положительный эффект.
Короче говоря:
- проверьте уровень изоляции
- проверьте свои транзакции
- создайте базовый уровень
- подумайте о READ_COMMITTED_SNAPSHOT
- проверьте свои индексы.
- обратная связь была бы приятной 🙂
Комментарии:
1. Вот интересная ссылка, которую вы можете проверить: sqlskills.com/help/waits/lck_m_u
2. Очень поучительный ответ и элегантный, я посмотрю, спасибо.
3. Большое спасибо, мы использовали область READ_COMMITED_SNAPSHOT, и наши задачи ожидания были сокращены до 10-20. Мы знаем компромисс, но для нас и требования важнее скорость, чем согласованность. Большое спасибо, чувак.
Ответ №2:
При плохой реализации Entity Framework, безусловно, может создать чрезмерную нагрузку на базы данных, так что это один из путей для изучения. Однако действительно необходимо исследовать возможные виновники и конкретные оптимизации для их устранения.
Наиболее распространенными проблемами с производительностью, с которыми я сталкиваюсь при использовании EF, являются такие вещи, как:
-
Отложенная загрузка. Здесь разработчики пишут запрос для загрузки объектов, затем перебирают их, получая доступ к связанным объектам, что вызывает дополнительные вызовы SQL для загрузки этих отдельных объектов. При запуске над наборами объектов это приводит к большому количеству ненужных запросов. Нетерпеливая загрузка связанных объектов (
Include
), где эти объекты необходимы, может заменить эти дополнительные обращения к БД объединениями. Более того, использование сквозного проектированияSelect
может привести к гораздо более эффективным запросам. -
Загрузка слишком большого количества данных, слишком часто. Такая простая вещь, как неуместные
ToList
вызовы, может привести к блокировке гораздо большего количества строк, чем необходимо. Обычно это происходит, когда разработчики сталкиваются с ситуациями, когда они хотят отфильтровать данные по вычисленным значениям (т.е. Результаты метода и т. Д. это не может быть переведено в SQL) и «исправление» заключается в добавлении aToList
, а затем оно волшебным образом работает. За кулисами EF материализует много нефильтрованных данных с сервера в память. Исправление здесь заключается в том, чтобы повторно хэшировать фильтрацию, чтобы больше фильтрации доходило до запроса, чтобы уменьшить объем извлекаемых данных.
Такие вещи, как общие классы репозиториев, являются мертвой отдачей для таких типов проблем, когда репозитории возвращают целые объекты или коллекции объектов, где доступны более эффективные варианты.
Классические примеры включают:
- Получение объекта обратно только для проверки, имеет ли оно значение null. (
.Any()
Вместо этого используйте запрос) - Получение списка объектов обратно только для подсчета. (
.Count()
Вместо этого используйте запрос) - Получение объекта, в котором требуется только небольшое количество столбцов. (Вместо этого используйте проекцию с
.Select()
)
EF может создавать очень эффективные запросы, но при плохой реализации это может привести к кошмарам взаимодействия с БД. К сожалению, без углубления в код и запуска вместе с профилировщиком невозможно перечислить конкретные улучшения, которые помогут.
Ответ №3:
Я вижу заблокированную транзакцию. Будет блокировщик. Если вы обнаружите, что head blocker — это запрос, который можно оптимизировать, это было бы началом. Это простые транзакции с одним запросом или это несколько запросов в транзакции? Вы делаете что-то, что заставляет вставки быть однопоточными, например, получаете последний идентификатор и добавляете 1 для нового идентификатора для вставки? Нужно ли блокировать другие транзакции?
Например, в загруженной базе данных мы обрабатывали новые записи. Мы быстро прочитали, чтобы обработать последнюю запись. Затем мы использовали предложение where для обработки записей только до этой записи. В противном случае вставки будут заблокированы транзакцией до тех пор, пока не будут обработаны все записи.