Насколько сильно компиляции SQL влияют на производительность SQL Server?

20

Я профилирую экземпляр SQL Server 2005 и с помощью SQLServer:SQL Statistics - SQL Compilations/secметрики PerfMon вижу, что среднее значение составляет около 170 или около того.

Я вынул SQL Profiler и искал события SP: Compile или SQL: Compile. Видимо их не существует. Я нашел Stored Procedure/SP:Recompileи TSQL/SQL:StmtRecompileсобытия. Объем данных, которые я вижу в профилировщике, позволяет предположить, что это неправильные события, хотя я не уверен.

Итак, мои вопросы. Ответы на любой из них были бы великолепны.

  1. Как я могу увидеть, что именно компилируется в SQL Server?
  2. Я выбрал неправильные метрики для просмотра? В Perfmon или в SQL Profiler?
  3. Что касается Stored Procedure/SP:Recompileи TSQL/SQL:StmtRecompileсобытий в SQL Profiler ... они не включают в себя метрику Duration. Как я могу измерить влияние этих событий на систему, если они не дают возможности увидеть влияние времени на систему.
AngryHacker
источник

Ответы:

33

Компиляции SQL / сек - хороший показатель, но только в сочетании с пакетными запросами / сек . Само по себе количество компиляций в секунду мало что говорит.

Вы видите 170. Если пакетное требование в секунду составляет всего 200 (немного преувеличено для эффекта), тогда да, вам нужно приступить к сути (наиболее вероятно чрезмерное использование специальных запросов и одноразовых планов). Но если ваш пакетный запрос в секунду измеряет около 5000, то 170 сборок в секунду совсем не плохо. Общее практическое правило заключается в том, что количество компиляций / сек должно составлять 10% или меньше, чем общее количество запросов в секунду .

Если вы действительно хотите углубиться в то, что кэшируется, запустите следующий запрос, который использует соответствующие DMV:

select
    db_name(st.dbid) as database_name,
    cp.bucketid,
    cp.usecounts,
    cp.size_in_bytes,
    cp.objtype,
    st.text
from sys.dm_exec_cached_plans cp
cross apply sys.dm_exec_sql_text(cp.plan_handle) st

Чтобы получить все одноразовые планы (количество):

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
)
select count(*)
from PlanCacheCte
where usecounts = 1

Чтобы получить соотношение количества планов одноразового использования по сравнению со всеми кэшированными планами:

declare @single_use_counts int, @multi_use_counts int

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @single_use_counts = count(*)
from PlanCacheCte
where usecounts = 1

;with PlanCacheCte as 
(
    select
        db_name(st.dbid) as database_name,
        cp.bucketid,
        cp.usecounts,
        cp.size_in_bytes,
        cp.objtype,
        st.text
    from sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) st
    where cp.cacheobjtype = 'Compiled Plan'
)
select @multi_use_counts = count(*)
from PlanCacheCte
where usecounts > 1

select
    @single_use_counts as single_use_counts,
    @multi_use_counts as multi_use_counts,
    @single_use_counts * 1.0 / (@single_use_counts + @multi_use_counts) * 100
        as percent_single_use_counts

Что касается продолжительности, полученной с помощью трассировки SQL Server, она недоступна для событий перекомпиляции. Не так важно видеть продолжительность или боль, которую вызывает компиляция плана, так как вы мало что можете сделать для конкретной ситуации. Решение состоит в том, чтобы попытаться ограничить компиляции и перекомпиляции посредством повторного использования плана (параметризованные запросы, хранимые процедуры и т. Д.).

Томас Стрингер
источник
9

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

  • Статистика SQL \ Пакетные запросы / сек
  • Статистика SQL \ Компиляции SQL / сек
  • Статистика SQL \ Перекомпиляции SQL / сек

Как отметил Томас Стрингер , хорошо следить за соотношением количества компиляций и запросов на пакет. Очевидно, чем ниже, тем лучше, но есть только рекомендации относительно того, что является «хорошим», и только вы можете решить, что является приемлемым. Абсолютная величина увеличения производительности, которую вы увидите, уменьшив количество компиляций, зависит от многих факторов.

Мне также нравится смотреть на соотношение перекомпиляции / компиляции , чтобы понять количество повторного использования плана запроса. Опять же, чем ниже, тем лучше. В этом случае, однако, вы хотите, чтобы перекомпиляция происходила в системе при изменении статистики (если БД доступна только для чтения и у вас есть перекомпиляции ... что-то может быть не так). Так же, как я сказал ранее, есть только руководящие принципы для того, что является "хорошим".

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

SELECT TOP 50
    qs.plan_generation_num,
    qs.execution_count,
    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
    WHERE qs.plan_generation_num > 1
    ORDER BY qs.plan_generation_num DESC

Если вы также записываете статистику использования ЦП, все статистические данные можно сопоставить, чтобы узнать, насколько это больно, и насколько помогают ваши исправления. На практике я обнаружил, что даже одна стратегия с плохим планом запроса на ядре может поставить сервер на колени; очевидно, YMMV.

Джон Сайгель
источник