Индексы — одна из самых мощных функций производительности в SQL Server. Но они также одни из самых непонятых. Многие разработчики считают, что добавление новых индексов автоматически улучшает производительность. К сожалению, часто бывает наоборот. Одна из самых распространённых проблем с производительностью SQL Server, которую я вижу в реальных системах, — это база данных, полная ненужных или плохо спроектированных индексов. Сегодня мы рассмотрим самую распространённую ошибку индексирования в SQL Server и способ её исправления.
22.3.26
Самая распространённая ошибка индексирования в SQL Server (и как её исправить)
20.3.26
Использование Claude Code с SQL Server
Эта статья не для тех, кто уже использует Claude Code. Я не хочу слышать жалобы от пользователей Code в комментариях о том, что я не осветил ту или иную функцию или сценарий. Это общий обзор на ~2000 слов о том, что это такое, почему вы можете этого захотеть, что вам нужно будет обсудить с вашей командой, и куда обращаться за дополнительной информацией.
Я также должен упомянуть, что я использую множество маркированных списков в своих обычных текстах. Как и во всех моих постах, ничего из этого не написано с помощью ИИ, точка. Эти слова исходят непосредственно из моего затуманенного алкоголем мозга, написаны в марте 2026 года, и, несомненно, со временем эта информация потеряет актуальность.
17.3.26
Как удалось убрал 32 секунды из запроса без добавления индекса
Это не теория.
Это не лабораторная настройка.
Это произошло с реальной рабочей нагрузкой.
Исходное время выполнения: 42 секунды.
После оптимизации: 9.8 секунды.
Никакого нового индекса.
Никакого изменения схемы.
Никакого обновления оборудования.
Просто понимание того, как работает движок.
Приятного чтения — давайте заставим SQL Server летать.
Продолжение серии статей, вот предыдущая: Всё ещё о Batch Mode… Параметры совместимости и опции запросов (Часть 6)
15.3.26
Всё ещё о Batch Mode… Параметры совместимости и опции запросов (Часть 6)
Назад к серии: Как указать Batch Mode для Rowstore, если его нет в плане (Часть 5)
Мы всё ещё говорим о пакетном режиме, потому что понимание того, когда он работает, так же важно, как и знание того, как его принудительно включить.
Сегодня мы углубимся: мы рассмотрим уровни совместимости, выделение памяти, оценку количества строк и флаги трассировки.
Приятного чтения, и пусть ваш CPU остаётся холодным при тяжёлых агрегатах!
13.3.26
Как указать Batch Mode для Rowstore, если его нет в плане (Часть 5)
Предыдущая статья: Без новых индексов или изменений схемы - запросы быстрее в 10 раз с Batch Mode для Rowstore (Часть 4)
Давайте пристально изучим Actual Execution Plan, и углубимся в изучение пакетного режима для строчного хранения.
12.3.26
Без новых индексов или изменений схемы - запросы быстрее в 10 раз с Batch Mode для Rowstore (Часть 4)
Надеюсь, вам нравится эта серия. Я искренне верю, что она может быть очень полезной для тех, кто профессионально использует SQL Server, как это делаю я уже более 20 лет (как летит время!).
Сегодня мы поговорим о пакетном режиме для строчного хранения (Batch Mode on Rowstore) и о том, как сделать ваш запрос в 10 раз быстрее без добавления каких-либо индексов.
Что ж... в Части 3 мы представили колоночные индексы и увидели, как выполнение в пакетном режиме может кардинально улучшить аналитические запросы.
Если вы пропустили предыдущую часть, вы можете прочитать её здесь:
Но вот в чём поворот.
Начиная с SQL Server 2019, вам не всегда нужен колоночный индекс, чтобы получить производительность пакетного режима.
SQL Server может активировать пакетный режим для строчного хранения.
И иногда... как я сказал вам в начале этой статьи... ваш запрос становится в 5 или 10 раз быстрее без добавления ни одного индекса. Поэтому я предлагаю вам продолжить чтение...
10.3.26
Фильтрованный индекс против индексированного представления и индекса с хранением в колонках (Часть 3)
В предыдущих статьях мы сравнили фильтрованные индексы и индексированные представления, поняв, в каких случаях каждый из них проявляет себя наилучшим образом.
Если вы пропустили Часть 2, вы можете прочитать её здесь:
👉 Фильтрованные индексы: сравнение производительности с примерами (Часть 2)
Сегодня мы добавляем в игру нового игрока.
Потому что, когда объём данных начинает расти… когда миллионы строк превращаются в десятки или сотни миллионов… мы получаем мощного нового союзника:
Колоночные индексы (Columnstore Indexes).
И это меняет всё.
8.3.26
Фильтрованные индексы: сравнение производительности с примерами (Часть 2)
Эта статья является продолжением предыдущего глубокого погружения в настройку производительности SQL Server!
Если вы пропустили Часть 1, вы можете прочитать её здесь:
Как фильтрованные индексы кардинально улучшают производительность запросов (часть 1)
В первой статье мы проанализировали, как фильтрованные индексы могут кардинально сократить логические чтения и оптимизировать планы выполнения.
Сегодня мы углубляемся и сравниваем фильтрованный индекс с индексированным представлением, используя практические, воспроизводимые SQL-скрипты.
Вы найдёте конкретные сценарии, которые сможете протестировать в своей собственной лаборатории — потому что настройка производительности — это не теория, это экспериментирование.
4.3.26
Устранение ошибок включения CDC — Часть 2
В предыдущей статье блога я рассказывал о сбое CDC из-за отключённого пользователя guest в MSDB. Тогда же мой заказчик столкнулся и с другой проблемой:
Msg 22832, Level 16, State 1, Procedure sp_cdc_enable_table_internal, Line 622 Could not update the metadata that indicates table [dbo].[Table_Name] is enabledfor Change Data Capture. The failure occurred when executing the command'insert into [cdc].[change_tables]'. The error returned was 515:'Cannot insert the value NULL into column 'has_drop_pending',table 'LLCProduction.cdc.change_tables'; column does not allow nulls.INSERT fails.'. Use the action and error to determine the cause of the failureand resubmit the request.
Они обошли её, включив параметр ANSI_NULL_DEFAULT на уровне базы данных:
ALTER DATABASE DB_Name SET ANSI_NULL_DEFAULT ON;
После этого CDC включился успешно.
Вопрос в том, какова первопричина этой проблемы и как мы можем избежать её в будущем?
27.2.26
Как фильтрованные индексы кардинально улучшают производительность запросов (часть 1)
Сегодня мы погружаемся в мощную технику настройки производительности SQL Server, которая может кардинально сократить логические чтения, оптимизировать планы выполнения и значительно улучшить производительность запросов в реальных производственных средах.
Если вы работаете с Microsoft SQL Server и боретесь с медленными запросами, высокими логическими чтениями или неэффективными планами выполнения, эта продвинутая техника настройки производительности SQL Server может кардинально улучшить производительность запросов.
В этой статье мы проанализируем, как фильтрованные индексы в SQL Server могут уменьшить ввод-вывод, оптимизировать планы выполнения и значительно повысить производительность OLTP.
26.2.26
Обнаружение длинных цепочек IAM
В предыдущей статье Любопытный случай периодического сбоя запроса к крошечной таблице я описал проблему, с которой Джонатан столкнулся у клиента: очень длинные цепочки IAM и обстоятельства, к ним приведшие.
Вопрос заключался в том, как доказать, что некоторые единицы распределения имеют длину цепочки IAM, непропорциональную объёму данных в единице распределения, без утомительного прохода по каждой цепочке IAM, начиная с первой IAM-страницы (чей идентификатор всегда хранится во внутренней таблице sys.allocation_units).
25.2.26
Как оптимизировать переключение реплик групп доступности SQL Server
Мы часто выполняем плановые переключения реплик в группах доступности SQL Server для обслуживания, установки исправлений, обновлений и даже ротации оборудования. Обычно наши переключения выполняются быстро, но иногда они занимают больше времени — и не всегда интуитивно понятно почему, поскольку нет очевидной связи со временем суток, размером базы данных или объёмом транзакций.
Сокращение даже нескольких секунд из этого процесса может улучшить взаимодействие с приложением и конечным пользователем; это также может значительно снизить количество оповещений или, по крайней мере, сократить время, в течение которого оповещения должны быть отключены. Существует множество материалов о том, как правильно выполнять переключения в AG (без потери данных), но гораздо меньше тех, которые сосредоточены на сокращении окна прерывания доступности. Разница обычно заключается в некоторой комбинации объёма повторного выполнения (redo), поведения контрольных точек, открытых транзакций и готовности вторичной реплики.
Я хотел поделиться некоторыми методами, которые я использую, чтобы сделать плановые переключения более быстрыми и предсказуемыми. Некоторые из этих методов хорошо документированы, другие выпестованы из реальных шаблонов, которые я наблюдал во многих средах с SQL Server. Я расскажу о том, что я делаю до, во время и после переключения первичной реплики, чтобы минимизировать прерывания работы пользователей и повысить вероятность того, что они не заметят, что что-то произошло.
24.2.26
Введение в транзакции SQL Server
Одним из фундаментальных понятий в любой реляционной системе управления базами данных (СУБД), такой как SQL Server, является транзакция. За свою консультационную карьеру я видел множество случаев проблем с производительностью, вызванных тем, что разработчики не понимают, как работают транзакции в SQL Server, поэтому в этом учебном руководстве я объясню, что такое транзакции и почему они необходимы, а также некоторые детали их работы в SQL Server. В использовании всего этого есть нюансы, когда задействовано Ускоренное восстановление базы данных (ADR) — темы для будущих статей.
10.2.26
Нечёткое сопоставление строк в SQL Server 2025
Нечёткое сопоставление строк (Fuzzy String Matching) — это процесс поиска строк, которые приблизительно равны, а не точно совпадают. Это критически важная возможность для очистки данных, дедупликации, простого поиска по естественному языку и сопоставления пользовательского ввода с известными значениями.
До сих пор возможности нечёткого сопоставления в SQL Server были ограничены фонетическими сравнениями. Но теперь SQL Server 2025 представляют набор современных функций сходства строк, которые можно запускать напрямую в T-SQL с гораздо большей точностью.
9.2.26
Детализация прав для динамического маскирования данных в SQL Server 2022
Динамическое маскирование данных (Dynamic Data Masking, DDM) — это функция безопасности, представленная ещё в SQL Server 2016. Она скрывает конфиденциальные данные в результирующем наборе запроса, гарантируя, что неавторизованные пользователи не увидят информацию, к которой не должны иметь доступ. Подробное введение в эту функцию можно найти в моей старой статье в блоге.
Эта статья объясняет новые возможности DDM, добавленные в SQL Server 2022, а именно — детализированные разрешения.
8.2.26
Большое количество планов выполнения для одного запроса
Я работал над запросом в службу поддержки, в котором наш клиент обнаружил большое количество планов выполнения, потребляющих ресурсы в кэше планов для одного запроса. Я хотел бы поделиться своими выводами и опытом по предотвращению подобных проблем.
7.2.26
Sniffing параметров в SQL Server
"Parameter Sniffing" (конфиденциальность параметров) в SQL Server происходит, когда план выполнения запроса генерируется с использованием конкретных значений параметров. Последующие выполнения того же запроса могут работать плохо с другими значениями параметров из-за неподходящего кэшированного плана. Вот как можно решить эту проблему:
6.2.26
Принудительные планы в SQL Server перезаписывают хэш запроса

Автор: Paul White, SQL Server Forced Plans Overwite the Query Hash
Если вы «принудительно» задаёте план, любым методом, включая руководство планом (Plan Guides), хранилище запросов (Query Store) и автоматическое исправление плана (Automatic Plan Correction), результирующий план будет иметь свой query_hash перезаписанным значением query_plan_hash.
Другими словами, хэш плана и хэш плана запроса получат значение хэша плана запроса. Реальное значение хэша запроса просто теряется. 🤦
Это нарушит работу всего, где вы используете query_hash для любых целей, включая скрипты и инструменты.
29.1.26
Автоматическое обновление статистики не всегда аннулирует кешированные планы выполнения
Обычно, когда SQL Server обновляет статистику по объекту, он также аннулирует кешированные планы выполнения, которые полагаются на эту статистику. Именно поэтому вы видите повторную компиляцию после обновления статистики: SQL Server знает, что статистика изменилась, и это хороший момент для построения новых планов выполнения с учётом изменений в данных.
Однако обновление статистики, созданной системой, не обязательно приводит к повторной компиляции планов.
Это действительно странный крайний случай, и вы, вероятно, никогда с ним не столкнётесь, но я сталкиваюсь с ним на каждом занятии, которое провожу. Я каждый раз мимоходом упоминаю об этом в классе и даже не обращаю на это особого внимания. Однако недавно студент спросил меня: «Это где-нибудь задокументировано?», и я подумал, э-э, может быть, но я не уверен, так что лучше задокументировать это здесь, в старом добром блоге.
28.1.26
Сериализация операций удаления из кластерных columnstore-индексов
На Stack Overflow у нас есть несколько таблиц с кластерными columnstore-индексами, которые отлично работают для большей части нашей нагрузки. Но мы недавно столкнулись с ситуацией, когда «идеальные штормы» — несколько процессов, пытающихся одновременно удалить данные из одного columnstore-индекса — перегружали процессор, поскольку они все запускались с высокой степенью параллелизма и боролись за завершение своей операции.