16.12.25

Новое значение статуса VLF

Автор: Paul Randal, New VLF status value

По крайней мере с тех пор, как я начал работать в команде SQL Server (сразу после выхода версии 7.0) и до недавнего времени, существовало всего два кода статуса VLF (виртуального файла журнала):

  • 0 = VLF не активен (т.е. его можно (повторно) активировать и перезаписать)
  • 1 = не используется, и, кажется, никто не помнит, что это раньше означало
  • 2 = VLF активен, потому что хотя бы одна запись журнала в нём «требуется» SQL Server по какой-либо причине (например, ещё не была включена в резервную копию журнала или не просканирована репликацией)

Несколько недель назад я узнал о новом коде статуса VLF, который был добавлен ещё в SQL Server 2012, но не был широко известен до недавнего времени (по крайней мере, я никогда с ним не сталкивался в реальных условиях). Я провёл несколько обсуждений с другом из Microsoft (Шоном Галларди, PFE и MCM из Тампа), которому удалось покопаться в коде, чтобы выяснить, когда он используется.

15.12.25

Что такое спинлок FCB_REPLICA_SYNC?

Автор: Paul Randal, What is the FCB_REPLICA_SYNC spinlock?

В списке рассылки MVP по платформе данных возник вопрос о том, что такое спинлок FCB_REPLICA_SYNC. Я ответил на вопрос и пообещал сделать небольшую запись в блоге, поскольку в сети не нашёл о нём никакой информации.

14.12.25

Read committed не гарантирует многого…

Автор: Paul Randal, Read committed doesn’t guarantee much…

Некоторое время назад я участвовал в переписке по электронной почте, где люди обсуждали некоторое «странное» поведение SQL Server. Проблема возникала в SQL Server 2016 при использовании уровня изоляции по умолчанию — read committed. Сценарий был следующим:

  1. Создать таблицу с несколькими столбцами
  2. Пакет 1: В одном окне SSMS выполнить следующее (что занимает 10 секунд):
    • Начать транзакцию
    • Вставить 1000 строк в таблицу с задержкой WAITFOR DELAY 0.01 секунды между каждой вставкой
    • Зафиксировать транзакцию
  3. Пакет 2: Во втором окне SSMS:
    • Выполнить SELECT * из таблицы

«Странное» поведение заключается в том, что когда выборка «Пакета 2» завершается после того, как была заблокирована транзакцией «Пакета 1», она возвращает не все 1000 строк (даже несмотря на то, что «Пакет 1» завершился). Более того, в зависимости от того, когда была запущена выборка «Пакета 2» в течение 10 секунд выполнения «Пакета 1», «Пакет 2» возвращает разное количество строк. Такое поведение также сообщалось и в более ранних версиях SQL Server. Это легко воспроизвести в SQL Server 2016/2017 и можно воспроизвести во всех более ранних версиях с одним изменением конфигурации (подробнее чуть позже).

12.12.25

Почему в моей таблице-куче много пустых страниц?

Автор: Paul Randal, SQLskills SQL101: Why does my heap have a bunch of empty pages?

У SQLskills есть инициатива вести блог на базовые темы, которую мы называем SQL101. Мы все пишем о вещах, которые часто делаются неправильно, технологиях, используемых неверно, или случаях, когда существует множество заблуждений, ведущих к серьёзным проблемам.

Вот вопрос, который мне часто задают (перефразирую):

«У меня есть большая таблица-куча, в которой пространство не освобождается, когда я удаляю большое количество записей, но когда я сжимаю базу данных, размер кучи уменьшается. Можете объяснить?»

11.12.25

Как оператор SELECT может изменить базу данных?

Автор: Paul Randal, SQLskills SQL101: How can a SELECT cause a database to change?

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

Это интересное заблуждение, о котором меня спрашивали на прошлой неделе: (перефразируя) «Наверняка операция SELECT не может привести к изменению базы данных, потому что она просто читает данные, а не изменяет их каким-либо образом, верно?».

Что ж, нет. На самом деле существует довольно много побочных эффектов у запросов, которые только читают данные и никогда не выполняют изменения данных (не считая, конечно, SELECT ... INTO). Вот четыре, которые сразу приходят на ум…

10.12.25

Производительность REGEX в SQL Server 2025 не так уж плоха!

Автор: Brent Ozar, Update: SQL Server 2025’s REGEX Performance Isn’t So Bad!

Ещё в марте 2025 года, когда Microsoft впервые анонсировала поддержку REGEX в SQL Server 2025 и Azure SQL DB, я провёл быстрое тестирование, и производительность была ужасающей. Она была плохой в трёх разных аспектах:

  1. Использование ЦП было ужасным — сжигалось 60 секунд процессорного времени для проверки нескольких миллионов строк
  2. Он отказывался использовать индекс
  3. Оценка кардинальности была ужасной, жёстко закодирована на уровне 30% от таблицы

После комментария Эрланда Соммарског в этом месяце я вернулся и снова запустил тесты с релизной версией SQL Server 2025. Отличные новости! Microsoft исправила 1 из проблем, и... ну, одна из них немного хитрая. Для демонстрации я собираюсь использовать большую базу данных Stack Overflow за апрель 2024 года, чтобы создать наихудший сценарий, затем начать с индекса на небольшой таблице Users и запросить её через regex, как мы делали в статье от марта 2025 года.

9.12.25

Как хранятся значения по умолчанию?

Автор: Paul Randal, How are default column values stored?

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

8.12.25

Почему страницы PFS нельзя восстановить

Автор: Paul Randal, Why PFS pages cannot be repaired

В Twitter состоялось краткое обсуждение того, почему страницы PFS (повреждённый заголовок, а не отдельные байты PFS) нельзя восстановить (поводом стал вопрос #sqlhelp о том, почему для них невозможно восстановление отдельной страницы, в отличие от других карт распределения базы данных). Для справки: их также нельзя исправить с помощью автоматического восстановления страниц с зеркала или в группе доступности (AG).

Страницы PFS встречаются каждые 8088 страниц в каждом файле данных и хранят байт информации о себе и о следующих 8087 страницах. Самая важная информация, которую они хранят, — это то, выделена ли страница (используется) или нет. Подробнее о страницах PFS и других картах распределения базы данных можно прочитать в этой записи блога.

Итак, почему их не может восстановить DBCC CHECKDB, когда все остальные карты распределения базы данных могут?

6.12.25

Что такое ожидания LOGMGR_RESERVE_APPEND?

Автор: Paul Randal, What are LOGMGR_RESERVE_APPEND waits?

Мне прислали вопрос по электронной почте о причине возникновения ожиданий LOGMGR_RESERVE_APPEND, и в следующем выпуске рассылки Insider я дал краткое объяснение. Это очень необычный тип ожидания, чтобы видеть его в качестве основного на сервере, и, по сути, его вообще редко встречают.

5.12.25

Код для анализа иерархии транзакций в журнале

Автор: Paul Randal, Code to analyze the transaction hierarchy in the log
Код для анализа иерархии транзакций в журнале транзакций SQL Server

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

Это обсуждение побудило меня написать код, который я давно собирался сделать, ещё когда в SQL Server 2012 появилось поле в записях журнала LOP_BEGIN_XACT, отслеживающее идентификатор родительской транзакции, что позволяет исследовать иерархию транзакций.

Он предоставляет две хранимые процедуры, sp_SQLskillsAnalyzeLog и sp_SQLskillsAnalyzeLogInner, где первая использует вторую, а вторая рекурсивно вызывает саму себя.

4.12.25

Сравнение одноколоночных, многоколоночных и фильтрованных статистик в SQL Server

Автор: Kendra Little, Comparing Single Column, Multi-Column, and Filtered Statistics in SQL Server

Статистики в SQL Server теоретически просты: они помогают оптимизатору оценить, сколько строк может вернуть запрос.

На практике? Всё быстро становится странным. Особенно когда вы начинаете фильтровать по нескольким столбцам или задаётесь вопросом, почему оптимизатор думает, что вернутся миллионы строк, когда вы знаете, что их всего несколько сотен тысяч.

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