Есть ли способ определить, выполняются ли запросы SQL Server в памяти или на диск?

13

Сегодня я столкнулся с набором хранимых процедур в приложении, которые неоднократно вызываются в течение длительного процесса. В каждой процедуре я нашел несколько различных операторов выбора, некоторые внутри циклов; неудивительно, что эти процедуры, используемые в настоящее время, выполняются в течение нескольких минут, тогда как интуиция ожидает, что они завершатся через несколько секунд.

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

Обработка каждой строки при импорте данных занимает 300 мс на строку, поэтому сравнительно небольшой импорт занимает несколько минут.

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

Я пытаюсь определить .... для этого явно неэффективного кода, насколько реально это влияет? Это стоит исправить?

Итак, вопрос:
- есть ли способ определить, какие таблицы целиком закреплены в памяти?
- есть ли способ включить трассировку, чтобы отслеживать вложенные хранимые процедуры, чтобы найти особенно дорогие порции?

Примечание: это на SQL Server 2008 R2

TBone
источник

Ответы:

12

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

SELECT  DB_NAME(st.dbid) Db,
        OBJECT_NAME(st.objectid, st.dbid) Prc,
        qs.execution_count,
        qs.total_logical_reads,
        qs.total_physical_reads,
        qs.statement_start_offset,
        qs.statement_end_offset,
        st.text
FROM    sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st;

SELECT  DB_NAME(database_id) Db,
        OBJECT_NAME(object_id, database_id) Prc,
        execution_count,
        total_logical_reads,
        total_physical_reads
FROM    sys.dm_exec_procedure_stats ps;

Первый разбивает это на утверждения, второй учитывает всю процедуру.

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

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

В приведенных выше DMV есть много дополнительных столбцов, которые могут вас заинтересовать.


Как индекс помогает уменьшить логическое чтение?

В SQL Server все данные организованы в блоки размером 8 КБ. Эти блоки называются «страницами».

Каждая таблица содержит мета-страницы, которые содержат информацию о структуре таблицы, а также страницы pata. Если индекс не существует, и вы выполняете запрос, такой как SELECT * FROM tbl WHERE Id = 7SQL Server, он должен искать эту или эти строки во всей таблице. Таким образом, он считывает по одной странице за раз, просматривает все строки на каждой странице, чтобы определить строки, которые соответствуют WHEREпредложению. Таким образом, если для хранения таблицы требуется 1 000 000 страниц, для выполнения этого запроса потребуется 1 000 000 логических операций чтения.

Если у вас есть индекс, SQL Server сортирует данные логически на страницах и создает связанный список между страницами. Это позволяет выполнять запросы с ORDER BYвыполнением без дорогой операции сортировки. Но более важно то, что при сортировке SQL Server добавляет в таблицу дерево B + . Дерево B + - это структура, сравнимая с индексом в книге, где поиск определенного ключевого слова позволяет мне непосредственно переходить на страницу, которая содержит ключевое слово. Типичная книга имеет только один уровень индекса, тогда как у дерева B + может быть несколько. Подумайте только о большой книге, в которой сам индекс состоит из нескольких страниц. В таком случае имеет смысл добавить дополнительный индексный слой, который сообщает нам, на какой странице Sдолжны быть найдены индексные слова, начинающиеся с .

Деревья B + оптимизированы таким образом, чтобы иметь как можно меньше уровней, обеспечивая при этом свойство, что любую запись в индексе можно найти, прочитав по одной странице на уровень индекса. Итак, примите приведенный выше WHERE Id = 7запрос, когда у вас есть индекс, отсортированный по Id. Допустим, индекс имеет 5 уровней. Теперь, чтобы найти все записи, соответствующие этому запросу, мне нужно прочитать одну страницу на уровень индекса (то есть 5 страниц). Это называется «поиск индекса». Если есть несколько записей, которые соответствуют требованиям, мне, возможно, придется некоторое время следить за отсортированным индексом, чтобы получить все из них. Но давайте предположим, что есть только одна запись.

Таким образом, без выполнения индекса этот запрос потребовал 1 000 000 операций чтения, а для индексов - 5 операций чтения. Несмотря на то, что логическое чтение является операцией в памяти, это все равно требует значительных затрат - фактически это самая дорогая операция в тривиальном запросе, подобном приведенному выше. Таким образом, уменьшение количества логических операций чтения, необходимых в 200 000 раз, ускорит ваш запрос на аналогичный коэффициент.

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

Себастьян Майн
источник
> «... сокращение их количества (например, путем добавления соответствующего индекса) может ускорить выполнение ваших запросов». Не могли бы вы объяснить, как добавление индекса уменьшит (?) Логическое чтение? Является ли логическое чтение синонимом сканирования таблицы?
1
Добавил объяснение к моему ответу выше.
Себастьян Майн
Благодарю. Даже если предположить, что правильные индексы есть во всех задействованных таблицах ... Я думаю, что разница между производительностью таблицы, закрепленной в памяти, и чтением с диска (предполагается, что одинаковые индексы в обоих сценариях) все еще огромна ... или в других Другими словами, добавление индексов даст вам меньше прироста производительности на машине с большим количеством оперативной памяти, чем на машине с меньшим объемом памяти .... правильно?
1
доступ к физическому диску явно на порядок дороже, чем доступ к памяти. Таким образом, принятие мер, чтобы избежать этого, приведет вас очень далеко. Вы все еще должны посмотреть на количество логических чтений в первую очередь при настройке запроса. Поддержание их на низком уровне, в свою очередь, приведет к снижению физического чтения. Существует также высокая вероятность того, что страницы не должны быть извлечены из кэша, что еще больше снижает необходимые физические чтения.
Себастьян Майн
2
Незначительный придурок - я думаю, что страницы 8 КБ :-). Хороший ответ.
onupdatecascade
3
  • Есть ли способ включить трассировку для отслеживания вложенных хранимых процедур, чтобы найти особенно дорогие части?

Вы можете использовать SQL Profiler. Когда вы запускаете трассировку, вы должны выбрать RPC Completed, SP Starting, SP StmtStarting и SP StmtCompleted (см. Изображение ниже)

введите описание изображения здесь

Это позволит вам увидеть каждый запрос, который выполняется внутри хранимых процедур. Это позволит вам увидеть, сколько раз вызывается вложенная хранимая процедура. Когда трассировка закончится, вы должны сохранить ее. Затем снова откройте его, и после этого вы сможете фильтровать (с помощью кнопки «Фильтры столбцов»), чтобы найти запросы, которые вызывают проблемы. (например: запросы, которые заняли более x чтений или длились более x секунд (длительность) ...)

Параметры профилировщика, которые я показал вам, также показывают план выполнения, который также очень помогает.

Даниэль Пакетт-Харви
источник
1

Это похоже на общий вопрос оптимизации запросов. Из вашего описания я бы:

  1. Посмотрите на код, чтобы увидеть, выполняет ли он построчную обработку. Если это так, то часто можно добиться улучшения порядка на несколько порядков путем реализации одной и той же логики с использованием наборов (несколько строк обрабатываются одновременно). Другими словами, если он действует как «цикл над каждой строкой», измените его на «обработать все строки». SQL превосходен в этом, потому что оптимизатор может выбрать один из более возможных методов, потенциально использовать параллелизм, убрать много накладных расходов, возникающих по одной строке за раз.
  2. Затем убедитесь, что есть индексы, которые поддерживают работу. Часто, опять же, порядки улучшения могут быть достигнуты с правильными индексами против нет. Это верно в отношении памяти и доступа к диску. Процессы могут все еще занимать часы со всем в ОЗУ, если в большом наборе данных нет подходящих индексов.
  3. Затем, установив логику и индексы, я посмотрю, помещаются ли затронутые страницы данных в память. На этом этапе, если доступ к диску все еще велик, анализ физических операций чтения и активности диска имеет смысл, поскольку все большие выгоды от оптимизации делаются на первых двух шагах.
onupdatecascade
источник