LINQ to SQL: слишком высокая загрузка ЦП: что происходит, когда несколько пользователей - PullRequest
1 голос
/ 01 мая 2010

Я использую LINQ to SQL и вижу, как взлетает загрузка процессора. Смотрите скриншот ниже. У меня три вопроса

  • Что я могу сделать, чтобы уменьшить использование ЦП. Я сделал профилирование и в основном удалил все. Поможет ли превращение каждого оператора LINQ to SQL в скомпилированный запрос?

  • Я также обнаружил, что даже в случае скомпилированных запросов простые операторы, такие как ByID (), могут занять 3 миллисекунды на сервере с 3,25 ГБ ОЗУ 3,17 ГГц - это станет медленнее на менее мощном компьютере. Или скомпилированный запрос будет тем быстрее, чем больше он будет использоваться?

  • Загрузка ЦП (на локальном сервере увеличивается до 12-15%) для одного пользователя будет умножаться на количество пользователей, обращающихся к серверу, - когда приложение помещается на работающий сервер. то есть 2 пользователя одновременно будут означать 15 * 2 = 30% загрузки ЦП. Если это так, то мое приложение ограничено максимум 4-5 пользователями одновременно. Или LINQ to SQL .net не разделяет использование процессора. альтернативный текст http://www.freeimagehosting.net/uploads/5f10e1f694.png

Ответы [ 5 ]

6 голосов
/ 01 мая 2010

Профиль. Профиль. Профиль.

Профиль, чтобы точно определить, какой запрос потребляет больше всего ресурсов, и повысить производительность этого запроса. Вы можете использовать свойство Log DataContext для просмотра SQL - см. эту статью . Вы можете получить планы запросов для запросов в SQL Server - см. эту статью .

Примеры способов улучшения запроса:

  • Добавить отсутствующие индексы.
  • Перепишите запрос, чтобы воспользоваться уже существующими индексами.
  • Не извлекайте слишком много данных за запрос - используйте подкачку страниц и извлекайте больше строк только по запросу. Не выбирайте поля, которые вам не нужны.
  • Не извлекайте слишком мало данных за запрос - не создавайте цикл, извлекающий по одной строке за раз. Получить много строк одновременно.

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

Затем снова выполните профилирование, чтобы увидеть следующий запрос-убийцу и повторяйте процесс до тех пор, пока ваша производительность не станет приемлемой.

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

3 голосов
/ 10 ноября 2010

Я заметил подобное поведение с некоторыми приложениями здесь; Используя ANTS Profiler, мы сократили загрузку ЦП до кода Linq to SQL. Мы нашли несколько основных мест, где это становится проблемой:

  1. Сложные запросы Linq to SQL. Использование нескольких объединений, а также ограничения предложений и т.п. Проблема заключается в том, что механизм Linq to SQL должен преобразовывать оператор C # в оператор SQL. Я считаю, что это преобразование по умолчанию можно использовать повторно, если один и тот же код вызывается одним и тем же DataContext, но если вы создаете новый DataContext для каждого выполнения, то код преобразования с интенсивным использованием ЦП выполняется каждый раз. Эту проблему можно решить либо путем замены сложного запроса Linq to SQL хранимой процедурой, либо с помощью предварительно скомпилированного запроса Linq to SQL ( Вот сообщение в блоге, показывающее, как создать скомпилированный запрос ).
  2. Отражение на основе присвоения свойств. Мы обнаружили, что простые запросы, такие как DataContext.Orders.FirstOrDefault(o => o.OrderID = orderID), могут сильно загружать процессор, так как они используют отражение, чтобы установить все свойства для возвращаемых значений из запроса. Мы не исследовали это за пределами этой точки; Мы просто заменили часть нашего кода на основе Linq to SQL стандартным доступом к данным на C # (например, SqlCommand, SqlClient) написанным от руки кодом, чтобы получить соответствующие данные столбца в соответствующие свойства, но только в тех местах, которые ANTS говорил нам, были наиболее важный. Внесение этого изменения обычно значительно снижало загрузку ЦП (например, снижение загрузки ЦП с 2000 мс до 39 мс).
  3. Общая проблема с производительностью Linq (не относится только к Linq to SQL); Хотя написание запросов Linq действительно приводит к большему количеству намеренного раскрытия кода, чем аналогичные итеративные подходы, мы обнаружили, что иногда запросы оказываются очень неэффективными (обычно путем многократного повторения коллекции или создания декартового произведения, где в действительности нет необходимости). , У меня нет примеров этого, но ANTS сумел помочь найти и эти проблемы (обычно в поисках чрезвычайно высокого числа обращений для конкретной строки кода). Обычно они могут быть исправлены с небольшими изменениями в запросе Linq (или в некоторых случаях заменой запроса Linq парами операторов).

Возможно, важно отметить, что наше использование Linq to SQL основано на файлах DBML, которые создает GUI, поэтому атрибуты украшают классы со всей информацией о сопоставлении столбцов и тому подобном.

Это именно то, что мы нашли в отношении Linq to SQL; Мне было бы интересно посмотреть, какой опыт у других. Я настоятельно рекомендую ANTS Performance Profiler для определения того, где в вашем приложении сконцентрирована загрузка ЦП; Обратите внимание, что если высокая загрузка ЦП основана на SQL (что не похоже на ваш случай), то ANTS, вероятно, не поможет (как и весь мой ответ :)).

1 голос
/ 27 сентября 2011

Недавно мы развернули большое приложение электронной коммерции, используя linq to sql и испытали нагрузку на процессор, очень похожую на ту, что вы описали.

После нескольких недель профилирования и отладки трассировки выяснилось, что злодейка выполняла jit-компиляцию запросов во время выполнения.

Мы прошли наш уровень данных и преобразовали все запросы в скомпилированные запросы, и наше использование ЦП мгновенно изменилось с постоянных 100% до среднего от 5% до 20% с некоторыми скачками до 80%, когда запросы были в первый раз.скомпилирован.

1 голос
/ 01 мая 2010

Скомпилированные запросы не будут «быстрее» при большем использовании. Основное преимущество скомпилированных запросов состоит в том, чтобы избавить ядро ​​LINQ от необходимости многократно выполнять процесс перевода при каждом его вызове.

Что касается использования процессора, то если это ваша машина для разработки, очень велики шансы, что что-то еще вызывает такую ​​высокую активность. Даже если это выделенный сервер базы данных, я бы настоятельно рекомендовал использовать SQL Profiler для изучения того, какие операторы генерируются вашими запросами LINQ. Может потребоваться настройка вашей схемы, кода или настроек базы данных, чтобы вернуть использование на более приемлемый уровень.

0 голосов
/ 01 мая 2010
  1. Существуют ли какие-либо общие запросы, которые можно кэшировать?
  2. Можно ли переписать запросы linq
  3. Большая часть обработки запросов выполняется на веб-сервере или в SQL?
  4. Используете ли вы сервер SQL и веб-сервер на одном компьютере? У вас есть тестовая среда, которая имитирует производственную среду?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...