Показаны сообщения с ярлыком Query Optimisation. Показать все сообщения
Показаны сообщения с ярлыком Query Optimisation. Показать все сообщения

13.7.26

Избыточное и недостаточное индексирование — насколько всё плохо на самом деле?

Автор: Paul Randal, Over and under indexing – how bad is it out there?

Как-то я запустил опрос, в котором предложил выполнить код для получения сводного списка количества таблиц на вашем сервере с различным числом некластерных индексов. Я получил результаты с более чем 1000 серверов по всему миру — огромное спасибо всем, кто прислал мне данные!

Победители:

  • Наибольшее количество некластерных индексов на одном кластерном индексе: 1032
  • Наибольшее количество некластерных индексов на одной куче: 148
  • Наибольшее количество кластерных индексов с нулевым количеством некластерных индексов на одном сервере: 185237
  • Наибольшее количество куч с нулевым количеством некластерных индексов на одном сервере: 88042

Вау!

Теперь перейдём к некоторым деталям…

12.7.26

Статистика ожиданий для одной операции

Автор: Paul Randal, Capturing wait stats for a single operation

Эта статья о настройке производительности, которая давно была в моём списке задач. Анализ статистики ожиданий — отличный способ изучить симптомы проблем с производительностью (см. мой каталог Wait Stats для получения дополнительной информации), но использование DMV sys.dm_os_wait_stats показывает всё, что происходит на сервере. Если вы хотите увидеть, какие ожидания возникают из-за одного запроса или операции в рабочей системе (например, влияние подсказок MAXDOP на количество и продолжительность ожиданий CXPACKET для запроса), то использование DMV обычно нецелесообразно — вам пришлось бы очистить статистику ожиданий и убедиться, что в системе не выполняется ничего, кроме исследуемого запроса/операции. Наиболее правильный способ сделать это — использовать расширенные события (Extended Events).

5.7.26

Оптимизация запросов: выражения в предложении WHERE, не допускающие поиска по индексу

Автор: Paul Randal, Adventures in query tuning: non-seekable WHERE clause expressions

За последние пару месяцев я выполнил много работы по настройке производительности, и в эти выходные обнаружил нечто, очень распространённое в реальных системах. Кимберли помогала мне оптимизировать один сложный план запроса и заметила в коде то, чего я не увидел, — это приводило к просмотру индекса вместо поиска по индексу. Несмотря на то, что план запроса использовал покрывающий некластерный индекс, способ написания кода заставлял индекс сканироваться.

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

3.7.26

Важные соображения при настройке производительности

Автор: Paul Randal, Important considerations when performance tuning

Что, по вашему мнению, является самым важным аспектом при настройке производительности, если бы пришлось выбрать что-то одно? Суть в том, что в общем случае ответ всегда «зависит», но некоторые вещи оказываются главной проблемой чаще, чем другие. Давайте пройдёмся по каждому возможному ответу и посмотрим, как сильно они могут повлиять на производительность, если что-то не так. Это ни в коем случае не исчерпывающий список того, что может вызвать проблемы, а просто мои размышления в конце воскресенья, как обычно.

19.6.26

Насколько сложно выбрать правильные некластерные индексы?

Автор: Paul Randal, How hard is it to pick the right non-clustered indexes?

На собрании группы разработчиков .NET в Редмонде, и во время того, как Кимберли рассказывала о пропущенных и лишних индексах, возник следующий вопрос:

«Какой некластерный индекс лучше всего использовать для запроса с условием WHERE lastname = 'Randal' AND firstname = 'Paul' AND middleinitial = 'S'

Кимберли сказала, что для этого случая порядок ключей не имеет значения. Я подумал секунду, а затем возразил, сказав, что наиболее селективный столбец должен быть первым. Мы согласились обсудить это с группой в конце, но я подумал ещё немного и понял (и признался группе), что она права – мне следовало бы знать, что не стоит подвергать сомнению знания Кимберли об индексировании… :-)

4.6.26

Отслеживание DOP Feedback с помощью Extended Events

Автор: Vivek Janakiraman, SQL Server 2025 Series : Degree Of Parallelism (DOP) Feedback Explained with Real-Time Demo!

Настройка параллелизма всегда была одной из самых сложных задач оптимизации производительности SQL Server. Администраторы баз данных часто тратят часы на точную настройку параметров MAXDOP, пытаясь найти идеальный баланс между производительностью и потреблением ресурсов.

С выходом SQL Server 2025 эта задача значительно упрощается благодаря обратной связи по степени параллелизма (Degree of Parallelism Feedback, DOP Feedback) — мощной функции интеллектуальной обработки запросов, которая автоматически оптимизирует выполнение параллельных запросов.

В этой статье мы рассмотрим:

  • Что такое DOP Feedback
  • Как отслеживать её с помощью расширенных событий (Extended Events)
  • Демонстрацию в реальном времени с несколькими сценариями
  • Как проверить, работает ли DOP Feedback на вашем сервере

2.6.26

Структуры хранения #4 – Memory-optimized columnstore


Автор: Hugo Kornelis, Storage structures 4 – Memory-optimized columnstore;

Настало время для следующей части моей серии о структурах хранения. Предыдущие части охватывали дисковое хранение строк, колоночные индексы и оптимизированное для памяти хранение. В этой части я рассмотрю комбинацию двух последних: оптимизированные для памяти колоночные индексы.

Оптимизированные для памяти колоночные индексы были представлены в SQL Server 2016. За это время я видел несколько эффектных маркетинговых презентаций Microsoft, в которых много говорилось о «аналитике в реальном времени» (real-time operational analytics). Новая тенденция, согласно которой аналитическая обработка больше не должна выполняться на устаревшей копии данных в отдельном хранилище, а непосредственно в OLTP-базе данных. Отчёты всегда были бы полностью актуальными, необходимость в ETL-конвейере отпала бы, а благодаря сочетанию оптимизированных для памяти структур для OLTP-нагрузок и колоночных индексов для аналитической обработки всё всегда было бы быстро. В теории.

Я больше не слышал термин «аналитика в реальном времени» после первоначального выпуска SQL Server 2016. А начиная с внедрения SQL Server 2017, я не припомню, чтобы слышал от кого-либо из сотрудников Microsoft использование терминов «оптимизированный для памяти» и «колоночный» в одном докладе, не говоря уже об одном предложении.

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

29.5.26

Представляем расширение StatisticsParser для SSMS


Автор: Brent Ozar, Announcing the SSMS StatisticsParser Extension

Если вы много занимаетесь настройкой запросов, то, вероятно, сталкивались с StatisticsParser.com от Ричи Рамп (Richie Rump). Теперь пользоваться им стало ещё проще.

Скачайте и установите расширение, затем выполните ваш запрос с включёнными SET STATISTICS IO, TIME ON, и после завершения щёлкните правой кнопкой мыши в окне запроса и выберите Parse Statistics.

28.5.26

Обходим шторм компиляций стороной

Автор: Luca Biondi, Check SQL Server Plan Cache Pollution (III) in 45 Seconds

Вы когда-нибудь задумывались, почему ваш ЦП достигает 100% при низком объёме запросов? В этой статье я разберу механизм «Штормов компиляции» (Compilation Storms) и покажу, как обнаружить узкие места типа SOS_CACHESTORE менее чем за минуту.

В двух словах

  • Стоимость компиляции (Compilation Cost): Такты ЦП тратятся впустую, когда SQL Server выполняет «Полную оптимизацию» (Full Optimization) многократно.
  • Тривиальные планы (Trivial Plans): Быстрый путь к выполнению, который пропускает оптимизацию на основе стоимости для простых запросов.
  • Триггеры перекомпиляции (Recompilation Triggers): Плохая статистика и изменения схемы (DDL) являются основными подозреваемыми в нестабильности кэша.
  • Предупреждение о спинблокировке (Spinlock Warning): Высокое время ожидания SOS_CACHESTORE означает интенсивную конкуренцию за кэш планов.

Управление высококонкурентной средой SQL Server — это игра на миллиметры. Мы часто говорим о «быстрых запросах», но редко говорим о налоге, который движок платит до того, как запрос вообще начнётся: о компиляции. Когда ваш кэш планов нестабилен, SQL Server входит в «Шторм компиляции», превращая ваши высококлассные ЦП в дорогие обогреватели. Давайте заглянем под капот.

26.5.26

Выметаем ядовитые планы из кэша SQL Server


Автор: Luca Biondi, Check SQL Server Plan Cache Pollution (II) in 45 Seconds

Вы исправили ad-hoc запросы, но ваш сервер всё ещё «колбасит»? В этой статье я расскажу, почему даже идеальная параметризация может привести к «токсичности повторного использования» (reuse toxicity) и массовым скачкам ЦП.

В двух словах

  • Параметризованное засорение (Parameterized Pollution): Засорение кэша — это не только «слишком много планов», но и повторно используемый «неправильный план». 
  • Токсичность повторного использования (Reuse Toxicity): План, оптимизированный для одной строки, принудительно применяется к набору из миллиона строк, убивая производительность.
  • Нестабильность планов (Plan Instability): Резкие колебания между min_worker_time и max_worker_time указывают на войну, вызванную Sniffing'ом параметров.
  • Решение: Используйте Query Store, идентификацию по query_hash и оптимизацию PSP в SQL Server 2022.

В предыдущей части этой серии мы очистили кэш от «мусорных» планов. Но горькая правда в том, что чистый код не гарантирует чистый кэш. Даже когда ваше приложение на 100% параметризовано, SQL Server всё ещё может страдать от другого вида засорения — логической токсичности. Это происходит, когда движок повторно использует неоптимальный план выполнения, потому что во время компиляции он «унюхал» (sniffed) непредставительный параметр.

25.5.26

Проверка кэша SQL Server на засорение одноразовыми планами


Автор: Luca Biondi, Check SQL Server Plan Cache Pollution (I) in 45 Seconds

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

В двух словах

  • Загрязнение кэша планов (Plan Cache Pollution) происходит, когда непараметризованные запросы создают тысячи бесполезных одноразовых планов выполнения. 
  • Вымывание памяти (Memory Starvation): Эти планы крадут пространство у буферного пула, вытесняя данные из памяти и увеличивая ввод-вывод. 
  • Исправление: Используйте параметризацию, sp_executesql или включите настройку «Optimize for Ad Hoc Workloads». 
  • SQL-запрос «Wow!»: Определите, какие именно ad-hoc запросы прямо сейчас засоряют ваш кэш. 

За 25 лет настройки производительности я видел, как миллионы долларов, вложенных в оборудование, оказывались бесполезными из-за плохих привычек кодирования. Один из самых распространённых молчаливых убийц — засорение кэша планов. Это технический эквивалент заполнения библиотеки идентичными книгами, в которых меняется только одна страница. Каждый раз, когда ваше приложение отправляет запрос вроде WHERE Id = 1, а затем WHERE Id = 2 без параметризации, SQL Server обрабатывает их как совершенно новую логику.

22.5.26

Адаптивные соединения (Adaptive Joins) и распределение памяти в SQL Server

Автор: Kendra Little, Adaptive Joins and Memory Grants in SQL Server

Адаптивные соединения (adaptive joins) позволяют оптимизатору выбирать между хэш-соединением (Hash Join) и соединением вложенными циклами (Nested Loop join) во время выполнения, что может быть фантастически полезно для производительности, когда оценки количества строк могут варьироваться. Недавно, когда Эрик Дарлинг (Erik Darling) преподавал двухдневный курс по T-SQL на PASS Community Data Summit, один из студентов спросил, почему план запроса, в котором адаптивное соединение во время выполнения использовало вложенные циклы, всё равно получило большое распределение памяти (memory grant).

Я не помнила ответа на этот вопрос, но замечательная вещь в совместном преподавании в том, что Эрик его знал: адаптивные соединения всегда начинают выполняться как хэш-соединения, а это означает, что они должны получить распределение памяти заранее. Даже если в итоге запрос переключается на вложенные циклы во время выполнения, это распределение памяти уже было выделено. Это имеет реальные последствия для использования памяти, особенно в средах с высокой конкурентностью (high-concurrency environments).

21.5.26

Когда TempDB растёт «вширь»: как RCSI и длинные транзакции незаметно разрушают SQL Server


Автор: Steve Stedman, When TempDB Grows “Up and to the Right”: How RCSI and Open Transactions Quietly Break SQL Server

Одна из самых опасных проблем SQL Server — та, которую вы не замечаете, пока диск не заполнится, а производственная система не упадёт. TempDB особенно хороша в таком типе отказа — она незаметно растёт в фоновом режиме, пока внезапно не становится проблемой для всех.

Недавно мы просматривали отчёт о распределении пространства TempDB (TempDB Allocation History Report), и он прекрасно проиллюстрировал проблему, с которой мы сталкиваемся всё чаще по мере того, как растёт применение READ COMMITTED Snapshot Isolation (RCSI). RCSI обычно является правильным выбором, но когда что-то идёт не так, TempDB может расти взрывным образом, и большинство команд не понимают почему, пока не становится слишком поздно.

20.5.26

«Нет, мы не обновляемся. Что мы упускаем?»

Автор: Thomas Rushton, “No, we’re not upgrading. What are we missing out on?”

SQL Server 2016 — покойся с миром, RIP, скатертью дорога (хотя последнее звучит как-то слишком сурово). SQL Server 2016 выходит из расширенной поддержки (extended support) 14 июля — в День взятия Бастилии, без комментариев — 2026 года. Это следует из политики фиксированного жизненного цикла Microsoft (Fixed Lifecycle Policy): выпуск, примерно пять лет основной поддержки (mainstream support), в течение которой вы получаете исправления, обновления безопасности, улучшения производительности и функциональности, и ещё примерно пять лет расширенной поддержки (extended support), в течение которой вы получаете обновления безопасности и не многое другое. После этой даты Microsoft крайне редко выпускает какие-либо обновления за пределами платной программы расширенных обновлений безопасности (Extended Security Update, ESU), поэтому продолжение использования продукта, срок поддержки которого истёк (EOL product), следует рассматривать как экстренную меру только для краткосрочного использования.

19.5.26

Чего ждёт SOS_SCHEDULER_YIELD в SQL Server: причины и реакция


Автор: Steve Stedman, Decoding SOS_SCHEDULER_YIELD Wait Type in SQL Server: Causes and Solutions

Узнайте о типе ожидания SOS_SCHEDULER_YIELD в SQL Server: выявите причины, такие как конкуренция за ЦП, и найдите решения для настройки производительности с помощью экспертных советов. Этот тип ожидания возникает, когда задача добровольно уступает своё время ЦП, чтобы позволить другим задачам выполняться, что является естественной частью модели кооперативного планирования SQL Server. Однако, когда эти ожидания становятся частыми или продолжительными, они могут указывать на глубинные проблемы, ухудшающие производительность системы, что делает критически важным понимание их последствий.

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

В этой статье мы разберём тип ожидания SOS_SCHEDULER_YIELD, изучим его причины и то, когда он становится проблемой для вашей среды SQL Server. Мы проведём вас через методы диагностики, чтобы выявить корневые проблемы, и предоставим практические решения для снижения их влияния. Будь вы администратором баз данных (DBA) или разработчиком, понимание и устранение этого типа ожидания поможет обеспечить работу вашей базы данных на пике эффективности.

18.5.26

Неудобная правда о скалярных функциях


Автор: Luca Biondi, The Dangerous Truth About Scalar Functions in 45 Seconds

Скалярные пользовательские функции (Scalar UDF) — это тихие убийцы производительности SQL Server. В этой статье я расскажу, почему они скрывают свою истинную стоимость и как превращают быстрый запрос в покадровую катастрофу.

В двух словах

  • Скалярные UDF принудительно вызывают покадровое выполнение (RBAR — Row-By-Agonizing-Row): они обходят мощные алгоритмы оптимизатора, основанные на работе с наборами данных. 
  • Подавление параллелизма (Parallelism): Традиционные скалярные функции заставляют весь ваш запрос выполняться в одном потоке. 
  • Скрытые затраты: Планы выполнения часто показывают стоимость UDF как 0%, маскируя огромные накладные расходы на ЦП. 
  • Исправление: Используйте встроенные табличные функции (Inline Table-Valued Functions, iTVF) или функцию встраивания скалярных функций (Scalar Inlining), появившуюся в SQL Server 2019+. 

15.5.26

Новая официальная документация о принудительной параметризации (Forced Parameterization)


Автор: Brent Ozar, New Official Documentation on Forced Parameterization

Я обожаю хорошую документацию.

Много лет я указывал людям на документацию SQL Server 2008 о принудительной параметризации (Forced Parameterization) — действительно полезном инструменте для уменьшения раздувания кэша планов, получения более точных переиспользуемых планов запросов и включения функций интеллектуальной обработки запросов (Intelligent Query Processing) SQL Server 2019 и 2022, многие из которых полагаются на один и тот же текст запроса, поступающий повторно с течением времени, чтобы настроить его. Однако эта документация была довольно скудной.

14.5.26

"Подводные камни" неявных преобразований


Автор: Luca Biondi, The Hidden Cost of Implicit Conversions in 45 Seconds

Неявные преобразования — это молчаливые убийцы производительности, которые превращают молниеносные поиск по индексу (Index Seek) в мучительно медленные просмотры индекса (Index Scan). В этой статье я
покажу вам, как обнаружить их за 45 секунд и вернуть ваши такты ЦП!

В двух словах

  • Убийство SARGability: Неявные преобразования не позволяют SQL Server эффективно использовать поиск по индексу. 
  • Накладные расходы на ЦП: Преобразование каждой строки в таблице во время сравнения значительно увеличивает использование ЦП. 
  • Старшинство типов данных (Data Type Precedence): SQL Server всегда преобразует тип с более низким приоритетом в тип с более высоким. 
  • Исправление: Согласуйте типы данных столбца и параметра или используйте явное приведение типов в правильном направлении. 

13.5.26

Бывают дни, когда я хочу бросить всё это с кэшем планов и Хранилищем запросов!

Автор: Brent Ozar, There Are Days When I Feel Like Giving Up on the Plan Cache and Query Store

В теории мониторинг производительности SQL Server довольно прост:

  1. Изучите главные типы ожиданий (wait types) на сервере.
  2. Найдите запросы, вызывающие эти типы ожиданий.
  3. Исправьте эти запросы или улучшите реакцию сервера на них (индексы, настройки и т.д.).

Но на практике шаг 2 ужасен, потому что:

  • Приложения отправляют на сервер баз данных непараметризованные строки.
  • Пользователи Entity Framework строят запросы с FromSqlRaw или string.Format().
  • Пользователи Entity Framework пишут запросы с .Contains, который создаёт непараметризованный список IN, даже когда ищут всего одно значение (в EF9 стало лучше).
  • Люди пишут неаккуратный динамический SQL, который просто вставляет значения прямо в строку запроса.
  • Разработчики SaaS-решений помещают каждого клиента в собственную базу данных, и планы не переиспользуются между базами данных.