Почему бы мне НЕ использовать опцию SQL Server «оптимизировать для специальных рабочих нагрузок»?

49

Я читал несколько замечательных статей, касающихся кэширования планов SQL Server, таких как эта: http://www.sqlskills.com/blogs/kimberly/plan-cache-and-optimizing-for-adhoc-workloads/

Почему даже есть опция «оптимизировать для специальных рабочих нагрузок»? Разве это не должно быть всегда? Независимо от того, используют ли разработчики специальный SQL или нет, почему бы вам не включить эту опцию в каждом экземпляре, который ее поддерживает (SQL 2008+), тем самым уменьшая переполнение кэша?

Какой-то парень
источник

Ответы:

45

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

Да, оптимизация для рабочих нагрузок adhoc отлично подходит для уменьшения раздувания кэша плана, но всегда сначала проверяйте это!

[Редактировать: Кален Делани рассказывает интересный анекдот, что она спросила одного из своих друзей-инженеров Microsoft, будут ли обстоятельства, когда было бы неуместно включать это. Он возвращается через несколько дней, чтобы сказать - представьте себе приложение, которое имеет МНОЖЕСТВО разных запросов, и каждый запрос выполняется ровно в два раза. Тогда это может быть неуместно. Достаточно сказать, что таких приложений не так много!]

[Редактировать: если большинство ваших запросов выполняются более одного раза (не ровно дважды); это, вероятно, было бы неуместно. Общим правилом было бы повернуть его, если в базе данных много разовых запросов adhoc; однако таких приложений пока не так много.]

Питер Шофилд
источник
9
+1 новые функции очень, очень редко включаются по умолчанию. Я не могу придумать каких-либо веских причин, чтобы не включать эту особую функцию - в худшем случае все ваши запросы одноразовые и в любом случае не выиграют от кэширования.
Аарон Бертран
1
Это «безопасный» ответ, основанный на здравом смысле и не затрагивающий вопрос. Спрашивающий хочет знать конкретный вариант использования, когда лучше НЕ включать эту функцию.
MikeTeeVee
2
MikeTeeVee - это может быть безопасный ответ, но это одна из тех функций, где я действительно не могу придумать причину, чтобы не включить его. Так как это так здорово, я просто хотел объяснить, почему он был выключен по умолчанию!
Питер Скофилд
21

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

Это самый безопасный вариант для включения и хорошо описан Брэдом здесь и Гленном Берри здесь .

--- for 2008 and up .. Optimize ad-hoc for workload 
IF EXISTS (
        -- this is for 2008 and up
        SELECT 1
        FROM sys.configurations
        WHERE NAME = 'optimize for ad hoc workloads'
        )
BEGIN
    DECLARE @AdHocSizeInMB DECIMAL(14, 2)
        ,@TotalSizeInMB DECIMAL(14, 2)
        ,@ObjType NVARCHAR(34)

    SELECT @AdHocSizeInMB = SUM(CAST((
                    CASE 
                        WHEN usecounts = 1
                            AND LOWER(objtype) = 'adhoc'
                            THEN size_in_bytes
                        ELSE 0
                        END
                    ) AS DECIMAL(14, 2))) / 1048576
        ,@TotalSizeInMB = SUM(CAST(size_in_bytes AS DECIMAL(14, 2))) / 1048576
    FROM sys.dm_exec_cached_plans

    SELECT 'SQL Server Configuration' AS GROUP_TYPE
        ,' Total cache plan size (MB): ' + cast(@TotalSizeInMB AS VARCHAR(max)) + '. Current memory occupied by adhoc plans only used once (MB):' + cast(@AdHocSizeInMB AS VARCHAR(max)) + '.  Percentage of total cache plan occupied by adhoc plans only used once :' + cast(CAST((@AdHocSizeInMB / @TotalSizeInMB) * 100 AS DECIMAL(14, 2)) AS VARCHAR(max)) + '%' + ' ' AS COMMENTS
        ,' ' + CASE 
            WHEN @AdHocSizeInMB > 200
                OR ((@AdHocSizeInMB / @TotalSizeInMB) * 100) > 25 -- 200MB or > 25%
                THEN 'Switch on Optimize for ad hoc workloads as it will make a significant difference. Ref: http://sqlserverperformance.idera.com/memory/optimize-ad-hoc-workloads-option-sql-server-2008/. http://www.sqlskills.com/blogs/kimberly/post/procedure-cache-and-optimizing-for-adhoc-workloads.aspx'
            ELSE 'Setting Optimize for ad hoc workloads will make little difference !!'
            END + ' ' AS RECOMMENDATIONS
END
Кин Шах
источник
7

Представьте себе рабочий сервер, который обслуживает только 5 различных запросов, но несколько тысяч таких в секунду. Вы являетесь командой разработчиков Microsoft SQL Server. Вы собираетесь возиться с кэшированием планов. Включаете ли вы это поведение по умолчанию, когда знаете, что некоторые из ваших крупнейших и наиболее критичных клиентов (например, внутренняя реализация SAP в Microsoft) работают в одном кампусе и используют то же кафе, что и вы?

Stu
источник
Комментарии не для расширенного обсуждения; этот разговор был перемещен в чат .
Пол Уайт
7

Когда вы включите опцию « Оптимизировать для специальных рабочих нагрузок », вы сделаете так, что специальные запросы, которые выполняются во второй раз, будут такими же медленными, как и первый, потому что вы будете компилировать план выполнения и извлекать те же данные ( без этого кешируется) те первые 2 раза.
Это может не иметь большого значения, но вы заметите это при тестировании запросов.
Так что же происходит сейчас, если эта опция не включена, а кэш заполнен одноразовыми специальными запросами?

Алгоритм управления кэшированием:

По мере появления этой функции оптимизации был также обновлен алгоритм управления кэшированием.
Статья Кимберли Триппа также ссылается на пост Калена Делани об этом изменении алгоритма.
Она объясняет это лучше всего:

Это изменение фактически вычисляет размер кэша плана, при котором SQL Server распознает наличие нехватки памяти и начинает удалять планы из кэша. Планы, которые будут удалены, - это дешевые планы, которые не использовались повторно, и это ХОРОШО.

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

Итак, теперь возникает вопрос:

    « Почему нам НУЖНО« Оптимизировать для специальных рабочих нагрузок », когда SQL Server позаботится об удалении неиспользуемых планов, когда это необходимо? »

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

Как узнать, когда мне нужно включить это?

Вот запрос, который я написал, чтобы показать вам, сколько Ad-Hoc планов вы сейчас кэшировали и сколько дискового пространства они потребляют (результаты будут меняться в течение дня - так что тестируйте его во время большой нагрузки):

--Great query for making the argument to use "Optimize for Ad Hoc Workloads":
SELECT S.CacheType, S.Avg_Use, S.Avg_Multi_Use,
       S.Total_Plan_3orMore_Use, S.Total_Plan_2_Use, S.Total_Plan_1_Use, S.Total_Plan,
       CAST( (S.Total_Plan_1_Use * 1.0 / S.Total_Plan) as Decimal(18,2) )[Pct_Plan_1_Use],
       S.Total_MB_1_Use,   S.Total_MB,
       CAST( (S.Total_MB_1_Use   * 1.0 / S.Total_MB  ) as Decimal(18,2) )[Pct_MB_1_Use]
  FROM
  (
    SELECT CP.objtype[CacheType],
           COUNT(*)[Total_Plan],
           SUM(CASE WHEN CP.usecounts > 2 THEN 1 ELSE 0 END)[Total_Plan_3orMore_Use],
           SUM(CASE WHEN CP.usecounts = 2 THEN 1 ELSE 0 END)[Total_Plan_2_Use],
           SUM(CASE WHEN CP.usecounts = 1 THEN 1 ELSE 0 END)[Total_Plan_1_Use],
           CAST((SUM(CP.size_in_bytes * 1.0) / 1024 / 1024) as Decimal(12,2) )[Total_MB],
           CAST((SUM(CASE WHEN CP.usecounts = 1 THEN (CP.size_in_bytes * 1.0) ELSE 0 END)
                      / 1024 / 1024) as Decimal(18,2) )[Total_MB_1_Use],
           CAST(AVG(CP.usecounts * 1.0) as Decimal(12,2))[Avg_Use],
           CAST(AVG(CASE WHEN CP.usecounts > 1 THEN (CP.usecounts * 1.0)
                         ELSE NULL END) as Decimal(12,2))[Avg_Multi_Use]
      FROM sys.dm_exec_cached_plans as CP
     GROUP BY CP.objtype
  ) AS S
 ORDER BY S.CacheType

Результаты: введите описание изображения здесь

Я не буду говорить « Когда у вас есть X МБ » или « Если X% вашего Ad Hoc одноразового использования », чтобы включить это.
Это не влияет на Sprocs, Triggers, Views или Parameterized / Prepared SQL - только на специальные запросы.
Моя личная рекомендация - просто включить ее в вашей среде Prod, но подумайте о том, чтобы отключить ее в вашей среде разработки.
Я говорю это только для Dev, потому что если вы оптимизируете запрос, выполнение которого занимает минуту или более, вы не хотите запускать его 3 раза, прежде чем увидите, как быстро он будет выполняться с кэшированием - каждый один раз, когда вы редактируете его, чтобы найти лучший дизайн оптимизации.
Если ваша работа не связана с этим весь день, то сходите с ума и попросите вашего БД включить его везде.

MikeTeeVee
источник
0

«Почему я НЕ должен использовать ....» В ходе некоторых исследований производительности, извлечение планов из кэша планов практически в режиме реального времени, при этом наблюдение за использованием ресурсов может быть очень полезным. «Оптимизация для рабочих нагрузок adhoc» может нарушить это, поскольку планы-заглушки adhoc не будут возвращать план при запросе кеша. В таком случае, если запрос и план не могут быть идентифицированы иначе, настройка может быть выключена и включена снова для исследования. Обратите внимание, что изменение настроек запросов запросов составлено с этого момента. Кроме того, каждый раз при изменении свойства 'server' проверяйте экземпляр nonprod в той же версии, чтобы проверить, очистит ли изменение кэш плана. Лично я ненавижу удивляться этому. (Например, изменение maxdop на уровне сервера обычно очищает кэш плана,

«Скомпилированная заглушка плана не имеет связанного с ней плана выполнения, и запрос дескриптора плана не вернет XML Showplan». http://technet.microsoft.com/en-us/library/cc645587.aspx

sql_handle
источник