- PVSM.RU - https://www.pvsm.ru -

Поводом написать эту статью стал весьма достойный обзор Как мы тестировали VMware vSAN... [1] компании КРОК. Обзор-то достойный, но в нем есть фраза, с которой я борюсь уже больше десятка лет. Админы СХД, виртуализаторы и интеграторы раз за разом повторяют: "Задержки в 5 мс — это отличный показатель". Даже цифра в 5 мс десять лет не меняется. Я это слышал вживую от весьма уважаемых админов уже не меньше десятка раз. От менее уважаемых — десятки, а уж сколько раз читал в интернете… Нет, нет, нет. Для OLTP нагрузок 5 мс, особенно так, как их обычно измеряют — это epic fail. Мне приходилось объяснять причины этого уже много раз, на этот раз я решил собрать свои мысли в переиспользуемую форму.
Сразу оговорюсь, что в упомянутой выше статье этих ошибок нет, скорее фраза сработала как триггер.
Всё что описано в данной статье, верно для распространенных СУБД, используемых для типичной бизнесовой OLTP. Больше всего у меня опыт с MS SQL Server, но, как минимум, для PostgeSQL, Oracle и Sybase многие моменты и выводы также останутся верны.
Производительностью СУБД обычно недовольны все. Если в крупной системе есть СУБД — а она, внезапно, почти всегда есть — то эта СУБД и есть узкое место. Ну или сразу станет узким местом, если начать оптимизировать всё остальное. И вот, приходит заказчик и говорит человеческим голосом: "Помоги! Спаси! Заплатили $NNNNNNNN за сервера и СХД, а скорость не растет! Уж и администратор настраивал и вендор консультировал, а всё равно не шевелится." Если разработчики системы подходят под определение Лаврова (обойдёмся без точной цитаты), а специалисты эксплуатации и сопровождения "борются с инцидентами перезагрузкой сервера", то часто и проблема простая и незатейливая: отсутствуют индексы, кривые запросы, фатальные ошибки настройки (про которые в документации жирным написано "так делать нельзя!!!"), излишние блокировки, взаимоблокировки и прочая простая и понятная ерунда. Таких случаев много, большинство, но не все. Если система в сложности или нагрузке перешла некоторый невидимый предел, то она либо сдохнет от этих проблем, либо перейдёт на следующий уровень.
IMHO, лучшим средством сейчас является SQL Server First Responder Kit [2], продвигаемый Брентом Озаром [3]. Этот инструмент развивается весьма активно. Еще есть достойный набор [4] от Гленна Берри [5], он тоже не забросил свой проект. Оба набора по-своему прекрасны, чтение комментариев и запросов в первый раз открывает много нового. Я сам всегда начинаю осматриваться с sys.dm_os_waitsats, беглого взгляда на Error log и выяснения, есть ли хоть сколько-то работающая система резервного копирования.
На этом уровне уже сервер не стоит под столом директора, диски уже не внутри сервера, а в СХД, разработчики знают про индексы, а администраторы уже умеют PowerShell, и менеджеры ИТ начинают говорить умные слова типа SLA и RPO/RTO. Вот на этом уровне возникает интересная ситуация:
Ан нет. Крокодил не ловится, не растет кокос, и производительность системы такая же или ниже чем на старом сервере. Смотрю в sys.dm_os_waitsats и вижу WRITELOG, PAGEIOLATCH_SH и PAGEIOLATCH_EX в топе, среднее время ожидания 5+ мс. Ну типично, чо: "Эй, админы и DBA, тут у вас дисковая система — bottleneck" и вот тут начинается старая песня про 5 мс:
Кстати, всё вышесказанное не только про "свои" сервера, но и про облачные сервисы и виртуализацию. Там есть кучка своей специфики, но типичная клиническая картина примерно та же: в меру оптимизированная БД, неглупые сотрудники разработки и сопровождения, по процессору и памяти резерв есть, "выхлоп" от дальнейших вложений почти равен нулю.
Так вот. Это вся песня про "5 мс" чушь и ерунда. Если вы сами такое говорите — читайте эту статью. А если вам такое говорят — готовьте аргументы. Раньше, когда я слышал эти слова, я злился, но я уже не злюсь. У меня, как у того горшка с петуньей из "Автостопом по галактике" только одна мысль: "Ну вот опять...".
Почему БД такая медленная? Ну казалось бы, типичный сервер с 20-64 ядрами на частоте 2-3 ГГц способен выполнить 50-150 миллиардов простых операций, а максимальные (синтетические) тесты баз данных показывают на подобных машинах всего лишь 10000-50000 транзакций в секунду. Эй! Это ж от миллиона до десятка возможных миллионов операций на транзакцию. Это не просто много, это очуметь как много.
Такого оверхеда стоят ACID [7]-требования к транзакциям.
К слову, буква-в-букву эти требования не выполняются почти нигде и никогда, а в распределённых системах просто никогда (CAP-теорема мешает). Для нашей ситуации скорее всего дороже других стоит требование "D", это требование обеспечивается ключевым механизмом всех распространенных OLTP СУБД: WAL, write-ahead log (PostgeSQL), он же журнал транзакций (SQL Server), он же REDO log (Oracle). Вот он — камень на шее производительности, и он же фундамент Durability транзакций.
Давайте ненадолго забудем про современные SSD, про крутые СХД. Пусть у нас есть сервер, в нем один или несколько дисков.
Любая транзакция, даже вставка одной записи, как минимум потенциально, а на самом деле почти всегда и реально — неатомарное действие. Нам почти всегда нужно изменить не только ту страницу, где лежит запись, но и страницы индексов, возможно, служебные страницы. При этом в одной транзакции одна и та же страница может поменяться много раз. Плюс у нас параллельно могут выполняться другие транзакции. Более того — соседние во времени транзакции постоянно "теребят" одни и те же страницы. Если мы будем дожидаться записи каждой страницы на диск перед продолжением действий, а именно это по сути требуется в Durability, то нам придётся записывать во много раз больше и ждать обязательного окончания каждой записи на энергонезависимый носитель. Никаких кешей, никакой перестановки операций в очереди, а иначе не будет целостности! Более того, нам как-то надо отмечать какие данные уже по фиксированным транзакциям, а какие — ещё нет (и какие были данные раньше). Для понимания — типичный одиночный жёсткий диск (HDD) в таком режиме даст 50-100 IOPS и это константа уже 20 лет. На одну даже маленькую транзакцию потребуется 5-10 операций записи. Ах, да, чтобы знать, что записывать — надо прочитать. Даже очень-очень высоконагруженные на запись OLTP системы читают в раза 3 больше чем пишут. Таким образом наша транзакция стоит 20-40 IO, а значит 0,2-0,8 секунд на диск.
2 транзакции в секунду. Маловато? Давайте попробуем раскидать по дискам? Ой, а нам надо всё равно дожидаться пока предыдущий запишется и параллельность в итоге отсутствует. Как быть? А давайте заведем файл-журнал в который будем последовательно записывать все операции записи в БД и отметки транзакций! Плюсы:
Такой журнал и называется write-ahead log/transaction log/REDO log.
Ура! Супер! Было 2 транзакции в секунду, стало 300 — улучшили в 150 раз. А какой ценой? Как выясняется, цена значительна:
Это объяснение очень упрощенное, "на пальцах". Для нашей темы этого хватит. WAL — ключевой, фундаментальный механизм обеспечения транзакционности, он обязательно write-through, доступ однопоточный только на последовательную запись, с точки зрения хранилища глубина очереди 1.
Тему write-ahead logging в БД должен хотя бы в минимальном объёме знать каждый, кто так или иначе администрирует СУБД, или инфраструктуру СУБД, или разрабатывает базы данных.
Производители СХД "с рождения" сталкиваются с СУБД. Именно для баз данных бизнес покупает эти безумно дорогие комплексы: от street price хранилищ Dell-EMC, HP, Hitachi, NetApp при верстке бюджета глаза наполняются слезами у большинства топ-менеджеров, если они, конечно, не получат процент от этой цены. Но тут есть инженерно-маркетинговый конфликт. Я его поясню на примере Dell-EMC, но только потому что помню, где у них документация.
Итак:
Закон Амдала [11] беспощадно говорит нам, что однопоточная низкопроизводительная нагрузка сделает бесполезными добавление процессоров, а производительность будет определяться именно журналом. Более того, в этот момент нам станет наплевать на производительность СХД в IOPS, а станет важным только latency.
Но не стоит сбрасывать со счетов другие дисковые операции — чтение и запись в файлы данных и в tempdb. Чтение — тоже "ждущая" операция. Пока страница данных не прочитана с диска в память, процессор её обрабатывать не может. Но для этих операций возможны большие очереди и перестановка операций в этой очереди: СУБД часто знает, какие страницы надо дозагрузить в память, какие сбросить на диск и ставит в очередь на чтение сразу много. Так как в этом сценарии важно, когда закончится последняя операция из пачки, то в этой нагрузке нам наоборот важнее IOPS, чем latency отдельной операции. Для понимания масштабов: операций чтения в типичной OLTP системе 85%-95%. Да-да-да, операций записи на порядок меньше.
Инженеры-разработчики СХД вендора плотно работают с вендорами СУБД, и отлично понимают все технические нюансы работы СУБД с дисковой подсистемой. Правильное планирование, разбиение и выделение дисковых ресурсов для СУБД — сложная и важная компетенция администратора СХД. У того же Dell-EMC даже базовые white-paper H14621 [12] и H12341 [13] по рекомендациям разбиения для SQL Server — по сотне страниц. Эй! Это не детальная дока, это самый общий white-paper! Там есть ещё куча специфичных (h15142 [14], h16389 [15]… там их тьма). Не отстают и "смежники" из VMware — Architecting Microsoft SQL Server on VMware vSphere [16]. Обратите внимание, это документы не только и не столько для DBA, сколько для админов инфраструктуры и СХД.
Ещё отмечу, что во всех этих документах нарезаются отдельные LUN для данных, для журналов и для базы tempdb. Да, где-то в свежих документах аккуратно говорят, что для All-Flash решений нет смысла отделять журналы на физически отдельные носители, но LUNы все ещё предлагают нарезать отдельно. Если данные и журналы свалить в один LUN, то с точки зрения ОС это будет одна очередь IO. И вот тут будет проблема. У операций с журналом latency станет сразу на порядок больше. А из-за того, что в очереди появятся неперемещаемые операции с журналом, просядет IOPS на файлах данных и tempdb. Это не "открытие века", это азбучная истина работы с БД. Она не устарела и не отменена с появлением All-Flash. Да, задержки на операции с SSD быстрее на порядок, чем на операции с HDD, но всё ещё на пару порядков медленнее операций с памятью. IO всё ещё узкое место СУБД.
И в технических документах правильно делается акцент, что в журналах транзакций не важно количество IOPS, а важно, чтобы latency была минимальной (в современных пишут, что менее 1 мс).
А маркетологам надо продавать. Гиперконвергентность! Виртуализация! Гибкость развертывания! Дедупликация! Простота настройки! Много-много IOPS! Красивые презентации, уверенный голос, строгие костюмы. Ну а как иначе продать решение с 6-7-значным ценником в долларах? За этим как-то забывается, что от СХД можно добиться либо latency, либо throughput, но не обоих сразу, что какая-нибудь лицензия на балансировщик нагрузки стоит как еще одна полка, что если интенсивная запись будет длиться больше часа, то оперативной памяти контроллеров не хватит и производительность просядет до "как будто кеша нет", что обучение сотрудников заказчика стоит еще 100000 рублей за первый курс, ну и подобные уловки…
То ли наслушавшись-начитавшись маркетологов, то ли от лени, то ли ещё из-за каких-то тараканов, но почему-то часто админы СХД делают примерно так. Берем большую полку, всю её объединяем в что-то плоское, нарезаем на thin provisioned LUNs и раздаём по LUN на сервер. Или по два, потому что "системный раздел хорошо дедуплицируется". А когда, я вижу, что с дисковой подсистемой со стороны SQL ад-ад-ад, то начинается та самая песня, что "5 мс отличный показатель", что "100000 IOPS", "Ваша нагрузка на СХД менее 5%"
НЕТ.
Когда какая-нибудь загрузка данных на ноутбуке разработчика выполняется 5 минут, а на 40 ядерном сервере с 1 ТиБ RAM и СХД за полмиллиона долларов та же самая задача выполняется час, то даже у самых терпеливых заказчиков появятся вопросы обоснованности затрат.
| Средняя задержка на разделе с WAL | никогда не будет в секунду больше транзакций, чем: |
|---|---|
| 5 мс | 200 |
| 1 мс | 1000 |
| 0,5 мс | 2000 |
| 0,1 мс | 10000 |
| 0,05 мс | 20000 |
Для OLTP перестаньте считать "утилизацию" и IOPS. Отдельно замечу — совсем не смотрите на IOPS с большой глубиной очереди: даже на разделах с данными большие очереди обычно короткий всплеск или что-то, что не влияет на реальную производительность OLTP.
Делить дисковое пространство на LUN — это не прихоть DBA. У базы данных есть несколько разных профилей нагрузки дисковой подсистемы. Как минимум можно выделить следующее:
tempdb — то же самое, что и работа с файлами данных, но чтений обычно 40-75% и отзывчивость на запись может быть важной. В современных системах MS SQL эта БД может быть загруженной в несколько раз сильнее, чем БД с данными. В некластерной конфигурации СУБД этот раздел должен быть исключен из всяких СХД-шных репликаций. Его содержимое после перезагрузки сервиса всё равно будет уничтожено.Есть и другие виды нагрузки, но они слегка экзотичны (например, может быть хранилище файлов, хранящихся в БД в виде каталога FileStream). У всех этих видов нагрузки разные, зачастую противоречащие требования к дискам. Если они все свалены на один раздел, то вы не только ухудшаете производительность, но очень важно, что лишаетесь возможности понять из-за чего система тормозит, а также лишаетесь возможности улучшить только ту часть которая требует улучшения без глобальных улучшений/апгрейдов СХД. Поэтому главная рекомендация:
Ознакомьтесь с рекомендациями производителя СХД и СУБД, постарайтесь разобраться "почему они так советуют" и спроектируйте систему с учетом разных видов нагрузки. Разнесите принципиально разные виды нагрузки на разные разделы.
Ну и до кучи
tempdb не нагружен, то, возможно, разработчики БД в следующей версии включат RCSI [18] и в 12 чаов ваша карета превратится в тыкву.Если говорить про MS SQL, то на самом деле есть некоторое количество способов снизить нагрузку на bottleneck журнала транзакций, может кому-то поможет:
INSERT. И, да, напомню, что если вы не открыли транзакцию явно, то поведением по умолчанию будет "каждая команда — отдельная транзакция".tempdb журнал транзакций "не настоящий". У него есть кеширование. Поэтому, если вам нужны промежуточные вычисления, то не делайте их в постоянных таблицах.Вот и всё. Нет никой магии. 20000 IOPS с 5 мс latency и с очередью 4-16 ничего не говорит о производительности СХД для задач OLTP. Для OLTP надо правильно размечать СХД, правильно выбирать метрику производительности и уметь измерять её.
На горизонте есть очень интересный новый участник борьбы за производительность систем хранения для БД. Это Intel Optane. У нынешних SSD "красивые" цифры производительности начинаются от глубины очереди 4, что на самом деле не очень жизненно. Плюс эта производительность на запись обеспечивается некоторым объёмом оперативной памяти внутри SSD, и, если запись идёт достаточно интенсивно, то потом наступает существенная деградация производительности. А еще у SSD ограничен ресурс. Да, у современных серверных и топовых "гражданских" он достаточно большой, но совсем не бесконечный [24]. И тут на сцене появляется Intel Optane: судя по тестам несерверных моделей (раз [25], два [26] ) задержки на случайных операциях на очереди глубины 1 выходят на уровень около 20 микросекунд. Это по сути без кеширования, без деградации. SSD при таком же профиле начинают тупить до 100-300 мкс. Ресурс уже сейчас [24] выходит за типичный ресурс SSD.
Ну цена, да. Но потенциально эта железка открывает новые горизонты производительности OLTP "традиционной", не in-memory архитектуры без отказа от ACID. А с другой стороны latency 20 мкс заставляет задуматься о судьбе "обычных" СХД. На low-latency требованиях им будет очень тяжело конкурировать с Optane (снова привет встроенным системам хранения?).
Это всё очень круто и я надеюсь на успех (и подешевление) Optane.
Автор: speshuric
Источник [29]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/postgresql/283153
Ссылки в тексте:
[1] Как мы тестировали VMware vSAN...: https://habr.com/company/croc/blog/414125
[2] SQL Server First Responder Kit: https://github.com/BrentOzarULTD/SQL-Server-First-Responder-Kit
[3] Брентом Озаром: https://www.brentozar.com/
[4] набор: https://www.sqlskills.com/blogs/glenn/sql-server-diagnostic-information-queries-for-june-2018/
[5] Гленна Берри: https://www.sqlskills.com/blogs/glenn/
[6] "красную зону кривой им. Шипилёва": https://habr.com/company/jugru/blog/338732/
[7] ACID: https://ru.wikipedia.org/wiki/ACID
[8] Как устроены базы данных: https://habr.com/company/oleg-bunin/blog/358984
[9] Как перестать называть журнал транзакций SQL Server лог-файлом и прекратить борьбу за его размер.: http://sqlcmd.ru/trans_log_internals-part01.html
[10] Tarantool: https://habr.com/company/oleg-bunin/blog/340062/
[11] Закон Амдала: https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BA%D0%BE%D0%BD_%D0%90%D0%BC%D0%B4%D0%B0%D0%BB%D0%B0
[12] H14621: https://www.emc.com/collateral/technical-documentation/h14621-microsoft-sql-server-best-practice.pdf
[13] H12341: https://www.emc.com/collateral/white-papers/h12341-sqlserver-bp-wp.pdf
[14] h15142: https://www.emc.com/collateral/white-papers/h15142-unity-ms-sql-wp.pdf
[15] h16389: https://www.emc.com/collateral/white-papers/h16389-unity-storage-with-microsoft-sql-server-wp.pdf
[16] Architecting Microsoft SQL Server on VMware vSphere: https://www.vmware.com/content/dam/digitalmarketing/vmware/en/pdf/solutions/sql-server-on-vmware-best-practices-guide.pdf
[17] на NUCах c SSD, как вариант, да: https://habr.com/company/croc/blog/342820/
[18] RCSI: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/snapshot-isolation-in-sql-server
[19] The Data Loading Performance Guide: https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008/dd425070(v=sql.100)
[20] устаревает: https://blogs.msdn.microsoft.com/sql_server_team/sql-server-2016-minimal-logging-and-impact-of-the-batchsize-in-bulk-load-operations/
[21] We Loaded 1TB in 30 Minutes with SSIS, and So Can You: https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008/dd537533(v=sql.100)
[22] Delayed Transaction Durability: https://docs.microsoft.com/en-us/sql/relational-databases/logs/control-transaction-durability?view=sql-server-2017
[23] In-Memory OLTP: https://docs.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/in-memory-oltp-in-memory-optimization?view=sql-server-2017
[24] большой, но совсем не бесконечный: https://3dnews.ru/938764/page-2.html
[25] раз: https://www.phoronix.com/scan.php?page=article&item=intel-optane-900p
[26] два: https://www.tomshardware.com/reviews/intel-optane-ssd-905p,5600.html
[27] eugeneb0: https://habr.com/users/eugeneb0/
[28] apatyukov: https://habr.com/users/apatyukov/
[29] Источник: https://habr.com/post/414269/?utm_source=habrahabr&utm_medium=rss&utm_campaign=414269
Нажмите здесь для печати.