Миф №29: исправить фрагментацию кучи можно, создав и затем удалив кластерный индекс.
Неееееет!!!
Это одно из худших действий, которые только можно совершить, если не считать сжатия базы данных.
Миф №29: исправить фрагментацию кучи можно, создав и затем удалив кластерный индекс.
Неееееет!!!
Это одно из худших действий, которые только можно совершить, если не считать сжатия базы данных.
Это короткая статья о мифах вокруг коэффициента заполнения (fill factor) — тему, которую я настойчиво прояснял ещё в Books Online для SQL Server 2005.
Миф №25: разные заблуждения о коэффициенте заполнения.
Все ложные
Это миф невероятно живуч, так что самое время развеять его — и заодно показать наглядный сценарий, подтверждающий вывод.
Миф №19: операция TRUNCATE TABLE не журналируется.
ЛОЖЬ
В пользовательской базе данных не существует «нежурналируемых» операций. Единственные операции, которые SQL Server выполняет без записи пользовательских изменений в журнал, относятся к хранилищу версий в tempdb.
NULL bitmap (NULL‑битовая карта) отслеживает, какие столбцы в записи имеют значение NULL, а какие нет. Она существует как оптимизация производительности, позволяющая движку хранения не загружать целиком всю запись в процессор, когда в списке SELECT есть столбцы со значениями NULL, — тем самым уменьшается число проверяющих операций в строках кеша процессора (см. ссылку с подробностями о работе кешей памяти CPU и протоколе MESI). Разберём три распространённых мифа:
Если вы когда‑нибудь задавались вопросом: «Почему SQL Server на Hyper‑V работает медленнее, чем должен?!», эта заметка может помочь. И да, если бы десять лет назад вы спросили меня о Hyper‑V, я бы, вероятно, лишь усмехнулся. Может, и раньше. Но суть в том, что эта платформа масштабируется, работает, и на фоне «весёлых» нововведений Broadcom/VMware (с соответствующей монетизацией), всё больше клиентов переходят на Hyper‑V. Как и с VMware, здесь важно внимательно отнестись к ряду ключевых настроек.
Спасибо Jeff Iannucci за совместную работу над этой статьёй и за его идеи. Он слишком долго напоминал мне подготовить этот пост и чек‑лист для клиентов — в итоге решил помочь и с написанием.
Мы в Straight Path в основном команда DBA, но нас часто просят помочь с развёртыванием SQL Server на виртуальных машинах Hyper‑V и спрашивают: «Каковы лучшие практики?». Многие (если не большинство) системных администраторов это всё и так знают. Но если вдруг нет, или если в вашей компании «все шляпы» приходится носить вам одному, мы собрали ключевые рекомендации, которые помогут обеспечить высокую доступность и стабильную производительность SQL Server на Hyper‑V.
Это не тайные знания. Но это те вещи, упущенные настройки и неверные решения, которые мы продолжаем встречать на практике, работая с новыми клиентами. И как в нашей статье «VMware and SQL Server best practices» нескольких лет назад, мне гораздо приятнее, когда вы сами находите и исправляете эти моменты, а уж потом зовёте нас для действительно интересных и нетривиальных задач!
Я уже пару раз писал о фантомных (ghost) записях и задаче их очистки (по сути, это единственные разъяснения, о которых мне известно), но сегодня один из MVP коллег спрашивал меня о настройке для отключения этой задачи — не смог её найти для своего клиента.
Мои прежние записи на эту тему:
Там объяснено, что такое фантомные записи и как работает процесс их очистки.
На больших системах задача очистки может не поспевать за остальной нагрузкой — без шансов «догнать». Это однопоточная задача: представьте 16‑ядерный сервер с массой операций удаления, и один поток, который на одном CPU каждые 5 секунд пытается убрать фантомные записи, образовавшиеся от удалений, выполненных всеми прочими CPU. Очевидно, что очистка будет отставать.
Проблема здесь в том, что задача очистки всё равно будет «всплывать» каждые 5 секунд (каждые 10 секунд в 2008) и начинать удалять фантомы, потенциально ухудшая производительность: удерживая страницы в буферном пуле, порождая журнальные записи и выполняя физические операции ввода‑вывода. Это также один из фоновых процессов, который способен инициировать IO на, казалось бы, полностью бездействующей системе.
Есть способ отключить задачу очистки — флагом трассировки 661, как описано в KB 920093. Но будьте крайне осторожны! Если вы её отключите, место, занятое удалёнными записями, НЕ будет освобождено для повторного использования SQL Server, пока вы явно не сделаете что‑то, чтобы его вернуть, например перестройку индекса.
Иногда предлагают «заставить» очистку пройтись по всему, выполнив скан таблицы или индекса (таким образом поставив все удалённые записи в очередь для очистки). Это альтернативный путь, но он всё равно использует ту же фоновую задачу, а на очень загруженной системе с очень большим числом удалений (внимание, обобщение! :-)) зачастую куда эффективнее убрать «удалённые‑но‑ещё‑не‑возвращённые» записи с помощью reorganize или rebuild индекса.
Включение этого трассировочного флага может дать выигрыш в производительности на системах с очень тяжёлой нагрузкой на операции удаления — но только если обращаться с ним осмотрительно. В общем случае такая настройка не рекомендуется, но, возможно, окажется полезной именно вам.
Одна из тем, о которых я люблю рассказывать, — журнал транзакций и механизмы журналирования/восстановления. Я читал доклад на эту тему и на PASS, и на SQL Connections, и в обоих случаях обещал опубликовать серию статей о глубинных внутренних аспектах операций журналирования. Перед вами первая из них. Другие мои статьи, посвящённые некоторым деталям журналирования:
А теперь — к делу.
В SQL Server в редакции Enterprise существует возможность, называемая быстрое восстановление (fast recovery). Она позволяет базе данных стать доступной для работы сразу после завершения первой фазы восстановления (REDO), ещё до окончания второй (обычно более долгой) фазы (UNDO). Если не понимаете, о чём речь, загляните в мою статью в TechNet Magazine — Ведение журнала и восстановление в SQL Server. Но как SQL Server добивается этого?
В предыдущей статье я подробно разобрал, как работают контрольные точки и что именно при этом происходит (см. «Как работают контрольные точки и что записывается в журнал транзакций»). А ещё ранее я писал, почему в буферном пуле на загруженной системе может казаться, что там непропорционально много «грязных» страниц tempdb; сейчас хочу чуть подробнее прояснить, почему так и как контрольные точки работают для tempdb. Чтобы посмотреть содержимое буферного пула, см. «Что находится в буферном пуле?».
Контрольная точка для tempdb выполняется только тогда, когда файл журнала tempdb заполнен на 70% — это делается, чтобы по возможности не допускать роста журнала tempdb (заметьте, что долго идущая транзакция по‑прежнему может, по сути, «заложить» журнал и не давать его очистить, как и в пользовательской базе).
Давно собирался написать про это; к тому же недавно наткнулся в сети на несколько не вполне точных объяснений работы контрольных точек, поэтому хочу коротко описать, как они устроены с точки зрения журнальных записей.
Недавно возник вопрос: если я обновил базу данных с SQL 2000 или более ранней версии, как понять, будут ли выполняться проверки чистоты данных (data purity), или нет?
Как известно, начиная с SQL Server 2005, DBCC CHECKDB включает проверки «чистоты данных». Они ищут значения столбцов, выходящие за допустимый диапазон для их типов данных. Для баз, созданных в SQL Server 2005 и новее, эти проверки всегда выполняются DBCC CHECKDB и не могут быть отключены. Для баз, созданных в более ранних версиях, всё чуть сложнее.
Этот вопрос всплывает время от времени, в последний раз — сегодня утром во время частного курса (сейчас читает Кимберли): каков размер обратного указателя у переадресованной записи? (И да, я давно не писал ничего по‑настоящему «технического»…)
В куче (heap) возможны переадресующие (forwarding) и переадресованные (forwarded) записи. Это случается, когда запись в куче разрастается так, что уже не помещается на текущей странице. В таком случае запись переносится на новую страницу, а в исходном месте остаётся маленькая переадресующая запись. Переадресующая запись указывает на новое местоположение записи, которая называется переадресованной. Это сделано как оптимизация производительности, чтобы не приходилось изменять все некластерные индексы у кучи из‑за нового адреса записи в этой куче.
Расщепление страниц (page splits) всегда считаются дорогими, но насколько же на самом деле? В этой статье я покажу пример, насколько больше становится журнал транзакций, когда страница в индексе вынужденно расщепляются. Я буду использовать DMV sys.dm_tran_database_transactions, чтобы это продемонстрировать. Список столбцов и краткие пояснения к каждому столбцу можно найти в Books Online — я вспомнил о её существовании благодаря кому‑то в Twitter (увы, не помню, кто это был, и не смог найти упоминание в поиске).
В этой статье я хочу развенчать распространённый миф о том, что null bitmap содержит биты только для допускающих NULL столбцов. Это не так — там по одному биту на каждый столбец в определении таблицы, при условии, что в таблице есть хотя бы один допускающий NULL столбец. «Неиспользуемые» биты всегда равны 1, то есть означают «NULL».
Правка 2016: Этот флаг трассировки требуется во всех версиях SQL Server включая SQL Server 2014. На каждом экземпляре SQL Server в мире он должен быть включён. В SQL Server 2016 поведение, включаемое этим флагом, стало значением по умолчанию, поэтому сам TF1118 больше не требуется и не оказывает эффекта.
Вокруг флага трассировки TF1118 существует немало путаницы и заблуждений. Он переключает выделение страниц в tempdb: вместо одиночных распределений для первых 8 страниц они сразу выделяются как экстент (8 страниц). Он применяется, чтобы при высокой нагрузке ослабить конкуренцию за карты распределения (allocation bitmap contention) в tempdb, которая бывает связана, например, с массовым созданием и удалением маленьких временных таблиц.
Есть несколько мест, которые способны вызвать путаницу, на каждом из которых я остановлюсь по порядку. Затем я докажу, что TF1118 по‑прежнему работает во всех версиях SQL Server вплоть до 2014 включительно.
В предыдущих статьях о FILESTREAM я разбирал структуру каталогов контейнера данных FILESTREAM и то, как сопоставлять каталоги с таблицами и столбцами базы данных. В этой статье я объясню, как и когда работает процесс сборки мусора FILESTREAM, поскольку, похоже, нигде это не задокументировано (даже в статье FILESTREAM Storage in SQL Server 2008, которую я писал для Microsoft — предполагаемая глубина не включала такой низкий уровень деталей). Похоже, существует немало путаницы вокруг того, как выполняются обновления данных FILESTREAM и когда удаляются старые версии файлов FILESTREAM. Я объясню, как всё устроено, а затем покажу на примере.
Периодически (ладно, честно говоря, очень часто) мой внутренний список «надо бы об этом написать» разрастается до таких размеров, что меня охватывает почти непреодолимое желание. К счастью, эти порывы заканчиваются тем, что я публикую сразу несколько записей — иначе кто знает, в какие неприятности я мог бы вляпаться? :-)
Для начала сегодня — довольно глубокие внутренности о том, как работает журнал транзакций в одной конкретной ситуации. Этот вопрос всплывал несколько раз на последних курсах по внутреннему устройству и обслуживанию, которые я вёл, в модуле про журнал транзакций, так что я решил написать статью, подтверждающую, что мой ответ верен. Проще всего сформулировать вопрос с картинкой, позаимствованной из моей статьи в журнале TechNet Magazine (Ведение журнала и восстановление в SQL Server).
Ещё в первых статьях блога я написал подробное описание «фантомных» записей (ghost records) и процесса их очистки — см. статью «Подробно об очистке фантомных строк». На занятии возник вопрос, который стоит разобрать отдельно: возникают ли «фантомные» записи в кучах (heap)? Ответ — нет, не при обычной работе.
После того как я написал FILESTREAM Whitepaper для Microsoft, мне стали часто задавать вопросы о структуре контейнера данных FILESTREAM. Контейнер данных FILESTREAM — это технический термин для структуры каталогов NTFS, где хранятся все данные FILESTREAM.
Каждый раз, когда я веду курс, меня удивляет, сколько администраторов баз данных не знают о мгновенной инициализации файлов (instant file initialization). Не желая повторять публикации, уже написанные другими, кратко: эта возможность позволяет создавать или увеличивать файл «мгновенно», без заполнения нового пространства в файле нулями. Это особенно полезно в сценариях аварийного восстановления, когда перед восстановлением базы данные файлы могут понадобиться впервые — с включённой мгновенной инициализацией исключается лишняя задержка. Подробности см. в записи Кимберли «Instant Initialization – What, Why and How?».
А теперь — к причине появления это статьи: хочу развеять несколько заблуждений, которые продолжаю слышать.
Этот вопрос прозвучал на одном из моих недавних занятий: если массив смещений столбцов переменной длины в записи хранит только смещения, то как механизм хранения находит конкретный столбец переменной длины?
Сомнение возникает потому, что в самой записи нет пометки, какой столбец переменной длины где расположен — как это работает? Ответ состоит из двух частей: это и NULL‑битовая карта (null bitmap) в записи, и метаданные таблицы/индекса, хранящиеся в системных таблицах. Все столбцы переменной длины имеют фиксированную «позицию» внутри переменной части записи в том случае, если их значение не равно NULL. Давайте покажу, что это значит.