Хабрахабр

Linux tuning to improve PostgreSQL performance. Илья Космодемьянский

Илья Космодемьянский “Linux tuning to improve PostgreSQL performance“

Расшифровка доклада 2015 года Ильи Космодемьянского "Linux tuning to improve PostgreSQL performance"

Часть поста, конечно, устарела, но здесь рассмотрен фундаментальный тюнинг PostgreSQL в Linux, который актуален и сейчас.

Меня зовут Илья Космодемьянский. Я работаю в компании PostgreSQL-Consulting. И сейчас буду рассказывать немножко про то, что делать с Linux применительно к базам данных вообще и к PostgreSQL в частности, потому что принципы довольно схожие.

О чем пойдет речь? Если вы общаетесь с PostgreSQL, то до какой-то степени нужно быть UNIX’овым админом. Что это значит? Если мы сравним Oracle и PostgreSQL, то в Oracle надо быть на 80 % DBA админом базы данных и на 20 % админом Linux.

С PostgreSQL немножко посложнее. С PostgreSQL надо сильно лучше представлять себе, как работает Linux. И при этом немножко бежать вслед за паровозом, потому что в последнее время довольно здорово все апдейтится. И новые ядра выходят, и новый функционал появляется, перфоманс улучшается и т. д.

Почему мы говорим про Linux? Совсем не по тому, что мы на конференции Linux Питер, а потому что в современных условиях одна из самых оправданных ОС для эксплуатации с базами данных вообще и с PostgreSQL в частности – это Linux. Потому что FreeBSD, к сожалению, развивается в каком-то очень странном направлении. И будут проблемы как с производительностью, так и с многими другими вещами. Производительность PostgreSQL на Windows – это вообще отдельная суровая тема, упирающая в то, что у Windows нет такой шаредной памяти как у UNIX, а у PostgreSQL все на это дело завязано, потому что многопроцессная система.

И экзотика типа Solaris, я думаю, в меньшей степени всех интересует, поэтому поехали.

У современного дистрибутива Linux более 1 000 параметров syctl, в зависимости от того, как собрать ядро. При этом, если мы посмотрим еще на разные гайки, то там можно еще многими способами что-нибудь поднастраивать. Есть параметры файловых систем, как монтировать. Если вопросы, как запустить: что в BIOS включить, как железки настроить и т. д.

Это очень большой объем, о котором можно рассказывать несколько дней, а не за один короткий доклад, но я сейчас остановлюсь на важных вещах, как избежать тех граблей, которые с гарантией не дадут вам хорошо эксплуатировать базу данных на Linux, если вы их не поправите. И при этом важный такой момент, что многие параметры по дефолту включены не в такие настройки, которые правильны для базы данных. Т. е. по умолчанию работать будет плохо или работать не будет вообще.

Какие традиционные tuning targets есть в Linux? Я думаю, что поскольку вы все имеете дело с администрированием Linux, то что такое targets объяснять особо не надо.

Можно тюнить:

  • CPU.
  • Memory.
  • Storage.
  • Other. Об этом мы поговорим в конце на закуску. Даже, например, такие параметры, как политика энергосбережения могут очень непредсказуемым и не самым приятным образом повлиять на производительность.

Какая специфика у PostgreSQL и у базы данных вообще? Проблема в том, что нельзя потюнить какую-то отдельную гаечку и посмотреть, что производительность у нас сильно улучшилась.

Да, такие гаечки есть, но база данных – это вещь сложная. Она взаимодействует со всеми ресурсами, которые есть у сервера и предпочитает взаимодействовать по полной. Если вы посмотрите на современные рекомендации Oracle по тому, как использовать хостовую ОС, то это будет как в анекдоте про того монгольского космонавта – покормить собаку и ничего не трогать. Дадим базе все ресурсы, база данных сама все разрулит.

В принципе, до некоторой степени с PostgreSQL точно такая же ситуация. Разница заключается в том, что база еще и не все ресурсы сама умеет себе забирать, т. е. где-то нужно на уровне Linux это все разруливать самостоятельно.

Основная идея – не выбрать какой-то единичный target и начать его тюнить, например, память, CPU или что-то в этом роде, а проанализировать workload и попытаться максимально улучшить пропускную способность, чтобы через нашу базу данных максимально эффективно проходила та нагрузка, которую добрые программисты нам создали, в том числе и наши пользователи.

Вот такая картинка для пояснения того, что это такое. Есть буфер ОС Linux и есть шаредная память и есть шаредные буфера PostgreSQL. PostgreSQL в отличие от Oracle работает непосредственно только через буфер ядра, т. е. чтобы страничка с диска попала в его шаредную память, она должна пройти через kernel buffer и обратно точно такая же ситуация.

Под этой системой живут диски. Я это нарисовал как диски. На самом деле там может быть RAID-контроллер и т. д.

И вот этот ввод-вывод так или иначе происходит через это дело.

PostgreSQL – это классическая база данных. Там внутри странички. И весь ввод-вывод происходит при помощи страничек. Мы страничками подымаем блоки в память. И если ничего не произошло, мы их просто прочитали, то постепенно они из этого кэша, из шаредных буферов тонут и попадают обратно на диск.

Если мы где-то что-то заменили, то у нас вся страничка помечается как грязная. Я их тут синим цветом отметил. И это значит, что эта страничка должна быть синхронизирована с блочным хранилищем. Т. е. мы, когда ее сделали грязной, сделали запись в WAL. И в какой-то прекрасный момент времени пришло явление под названием checkpoint. И в этот лог записалась информация о том, что он пришел. И это значит, что все грязные странички, которые здесь были в этот момент в этих шаредных буферах, они синхронизировались с диском хранилища с помощью fsync через kernel buffer.

Для чего это делается? Если у нас пропало напряжение, то мы не получили ситуацию, что все данные пропали. Персистентная память, о которой нам все рассказывали, это пока что в теории баз данных – это светлое будущее, к которому мы, конечно, стремимся и оно нам нравится, но пока что они живут еще в минус 20 лет. И, конечно, за всем этим нужно следить.

И задача максимизации пропускной способности – это потюнить на всех этих этапах, чтобы это все ездило туда-сюда быстро. Шаредная память – это в основном страничный кэш. В PostgreSQL мы отправили запрос select что-то там, он достал эти данные из диска. Они попали в шаредные буфера. Соответственно, чтобы это работало лучше, должно быть много памяти.

Для того чтобы это все работало хорошо и быстро, вам нужно правильно настроить на всех этапах операционную систему. И выбрать сбалансированно железо, потому что если у вас в каком-то месте будет дисбаланс, то вы можете сделать очень много памяти, но обслуживаться она будет с недостаточной скоростью.

И пройдемся по каждому из этих пунктов.

Чтобы эти странички путешествовали туда-сюда быстрее, нужно добиться следующего:

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

Если у вас 512 GB оперативной памяти в сервере и все это в финале приезжает на SATA жесткий диск без всякого кэша, то весь сервер базы данных превращается не просто в тыкву, а в тыкву с SATA интерфейсом. Вы будете упираться в это непосредственно. И ничего вас не спасет.

Что касается первого пункта с памятью, то есть три вещи, которые могут сильно осложнить жизнь.

Первая из них – это NUMA. NUMA – это вещь, которая сделана для того, чтобы улучшить производительность. В зависимости от workload можно оптимизировать разные вещи. И в новом ее нынешнем виде она для таких приложений, как база данных, использующих интенсивно page cache шаредные буфера, не очень хороша.

В двух словах. Как понять, что с NUMA что-то не то? У вас какой-то неприятный стук, внезапно какой-нибудь CPU оказывается перегружен. При этом вы анализируете запросы в PostgreSQL и видите, что ничего такого там похожего нет. Эти запросы не должны настолько интенсивно потреблять CPU. Ловить это можно долго. Проще воспользоваться с самого начала правильной рекомендацией, как настроить NUMA для PostgreSQL.

Что на самом деле происходит? NUMA – это Non-Uniform Memory Access. Смысл в чем? У вас есть CPU, с ним рядом есть память его локальная. И эта память interconnects может подтягивать память с других CPU.

Если вы запустите numactl --hardware, то вам выйдет такая большая простыня. Среди прочего там будет поле distances. Будут циферки – 10-20, что-то в этом роде. Эти циферки ни что иное, как количество хопов, чтобы эту удаленную память подцепить и использовать локально. В принципе, хорошая идея. Это хорошо ускоряет производительность при ряде нагрузок.

Теперь представьте, что у вас один CPU сначала пытается использовать свою локальную память, потом пытается подтянуть по interconnect другую память себе для чего-нибудь. И на этот CPU попадает весь ваш page cache PostgreSQL – все, сколько-то там гигабайт. Вы всегда получаете худший случай, потому что на CPU непосредственно в этом модуле памяти обычно мало. И вся память, которая обслуживается, ходит через эти interconnects. Получается медленно и печально. И у вас процессор, который обслуживает этот узел, постоянно перегружен. И время доступа этой памяти – плохое, медленное. Эта та ситуация, которую вы не хотите, если используете это дело для базы данных.

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

Почему так? Казалось бы, что должно быть наоборот. Это происходит по одной простой причине, что памяти нам нужно под page cache много – десятки, сотни гигабайт.

И если мы это все выделили и прокэшировали наши данные там, то выигрыш от использования кэша будет существенно больше, чем выигрыш от такого хитрого обращения к памяти. И мы таким образом выиграем не сопоставимо по сравнению с тем, что мы будем более эффективно обращаться к памяти с использованием NUMA.

Поэтому подхода здесь два на данный момент, пока светлое будущее не наступило, и база данных не умеет сама разбираться на каких CPU она работает и откуда ей что-то нужно подтянуть.

Поэтому правильный подход – это вообще отключить NUMA, например, при перезагрузке. В большинстве случаев выигрыши бывают на такие порядки, что вообще не возникает вопроса, как лучше.

Есть другой вариант. Мы им чаще пользуемся, чем первым, потому что, когда к нам приходит на поддержку клиент, то для него перезагрузить сервер – это целое дело. У него там бизнес крутится. А проблемы из-за NUMA они испытывают. Поэтому мы стараемся отключить менее инвазивными способами, чем reboot, но тут аккуратней проверяйте, что она отключилась. Потому что, как показывает опыт, что на родительский процесс PostgreSQL NUMA мы отключаем, это хорошо, но совершенно не обязательно, что это сработает. Надо проверять и смотреть, что она действительно отключилась.

Есть хороший пост Robert Haas. Это один из коммитеров PostgreSQL. Один из ключевых разработчиков всех низкоуровневых потрохов. И если по ссылкам из этого поста пройтись, то там описывается несколько колоритных историй про то, как людям NUMA осложняла жизнь. Посмотрите, изучите чек-лист сисадминский, что нужно настроить на сервере для того, чтобы у нас база данных работала хорошо. Вот эти настройки нужно записать и проверять, потому что иначе будет не очень хорошо.

Обращаю внимание, что это касается всех настроек, про которые я буду говорить. Но обычно базы данных собирают в режиме master-slave для отказоустойчивости. Не забудьте внести эти настройки на slave, потому что в один прекрасный момент у вас случится авария, и вы переключитесь на slave, и он станет мастером.

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

Следующий момент – это huge pages. Huge pages сложно протестировать отдельно, да и смысла в этом нет, хотя есть бенчмарки, которые умеют это делать. Они легко нагугливаются.

В чем смысл? У вас не очень дорогой сервер, в котором много оперативной памяти, например, больше 30 GB. У вас не используется huge pages. Это значит, что у вас однозначно есть overhead по использованию памяти. И этот overhead далеко не самый приятный.

Почему так? И что происходит? Операционная система мелкими кусочками выделяет память. Так удобно, так исторически сложилось. И если вдаваться в подробности, то ОС должна транслировать виртуальные адреса в физические. И это процесс не самый простой, поэтому ОС результат этой операции кэширует в Translation Lookaside Buffer (TLB).

И поскольку TLB – это кэш, то в такой ситуации возникают все присущие кэшу проблемы. Во-первых, если у вас очень много оперативной памяти и она вся выделена мелкими chunks, то этот буфер становится очень большим. А если кэш большой, то по нему искать медленней. Overhead здоровый и он сам занимает место, т. е. оперативную память потребляет что-то нечто неправильное. Это раз.

Два – чем больше разрастается кэш в такой ситуации, тем больше вероятность того, что у вас будет cache misses. И эффективность этого кэша стремительно падает с ростом его размера. Поэтому в операционных системах придумали простой подход. В Linux он давно уже используется. В FreeBSD не так давно появился. Но мы говорим о Linux. Это huge pages.

И тут нужно отметить, что huge pages, как идея, изначально была продавлена сообществами, включавших в себя Oracle и IBM, т. е. производители баз данных крепко думали о том, что это пригодится, для баз данных в том числе.

И как это подружить с PostgreSQL? Во-первых, в линуксовом ядре должны быть включены huge pages.

Во-вторых, они должны быть в явном виде указаны sysctl параметром – сколько их. Цифры здесь из какого-то старого сервера. Вы можете посчитать, сколько примерно у вас shared buffers, чтобы huge pages туда влезали.

И если у вас весь сервер отдан под PostgreSQL, то хорошая отправная точка – это либо 25 % оперативной памяти отдать под шаредные буфера, либо 75 %, если вы уверены, что в эти 75 % ваша база данных точно поместится. Отправная точка первая. И считайте, если у вас 256 GB оперативной памяти, то, соответственно, 64 GB у вас будет шердных буферов. Посчитайте примерно с некоторым запасом – во что у вас должна быть выставлена эта цифра.

До версии 9.2 (если не ошибаюсь, с версии 8.2) можно было с помощью сторонней библиотеки подружить PostgreSQL с huge pages. А это всегда нужно делать. Во-первых, вам нужно, чтобы ядро умело выделять huge pages правильно. А, во-вторых, чтобы приложение, которое с ними работает, могло ими воспользоваться. Просто так оно не воспользуется. Поскольку PostgreSQL выделял память в стиле system 5, то это можно было сделать с помощью libhugetlbfs — это полное название библиотеки.

В 9.3 улучшили производительность PostgreSQL при работе с памятью и отказались от system 5 метода выделения памяти. Все очень обрадовались, потому что иначе пытаешься запустить два instances PostgreSQL на одной машине, а он говорит, что у меня шаредной памяти не хватает. И говорит, что нужно поправить sysctl. А там такой sysctl, что нужно еще перезагрузиться и т. д. В общем, все обрадовались. Но выделение памяти mmap сломало использование huge pages. У нас большинство клиентов используют большие shared buffers. И мы настоятельно рекомендовали не переходить на 9.3, потому что там overhead начинался в хороших процентах исчисляться.

Но зато community обратило внимание на эту проблему и в 9.4 очень хорошо переработали это мероприятие. И в 9.4 появился параметр в postgresql.conf, в котором можно включить try, on или off.

Try – наиболее безопасный параметр. При старте PostgreSQL, когда он выделяет шаредную память, он пытается отхватить себе из huge pages эту память. И если не получается, то откатывается на обычное выделение. И если у вас FreeBSD или Solaris, то вы можете поставить try, это всегда безопасно.

Если on, то он просто не стартует, если не смог выделить из huge pages. Тут уже – кому и что более мило. Но если у вас стоит try, то проверяйте, что у вас действительно то, что нужно выделилось, потому что пространств для ошибки там много. Сейчас этот функционал работает только на Linux.

Еще одно маленькое замечание, перед тем, как пойдем дальше. Transparent huge pages – это не про PostgreSQL пока что. Воспользоваться ими по нормальному он не может. И при Transparent huge pages для такого workload, когда нужен большой кусок шаредной памяти, плюсы наступают только при очень больших объемах. Если у вас терабайты памяти, тогда это может играть роль. Если мы говорит о более житейских применениях, когда у вас 32, 64, 128, 256 GB памяти на машине, то обычный huge pages – это Ok, а Transparent просто отключаем.

И последняя вещь, касающаяся памяти, непосредственно не связана с фрупутом, она может очень сильно испортить жизнь. Вся пропускная способность сильно пострадает от того, что сервер постоянно свапится.

И это будет очень неприятно в ряде моментов. И основная неприятность заключается в том, что в современных ядрах немножко разнится поведение с более старыми ядрами Linux. И эта вещь, на которую наступать довольно неприятно, потому что, когда мы говорим о какой-то работе с swap’ом, заканчивается это не своевременным приходом OOM-killer. И OOM-killer, который не своевременно пришел и скинул PostgreSQL, это неприятно. Об этом узнают все, т. е. до последнего пользователя.

Что происходит? У вас там большое количество оперативной памяти, все хорошо работает. Но почему-то сервер висит в swap’е и тормозит из-за этого. Казалось бы, памяти много, но так происходит.

Раньше мы советовали vm.swappiness ставить в ноль, т. е. отключать swap. Раньше казалось, что 32 GB оперативной памяти и шаредные буфера соответствующие – это огромное количество. Основное назначение swap’а, чтобы было место, куда кинуть корку, если мы отвалились. И оно уже не особо выполнялось. И что потом с этой коркой будешь делать? Это уже такая задача, когда не очень понятно, зачем swap нужен, тем более такого размера.

Но в более современных, т. е. в третьих версиях ядра поведение изменилось. И если выставить swap в ноль, т. е. выключить, то рано или поздно даже при остатке некой оперативной памяти к вам будет приходить OOM-killer, чтобы убивать наиболее интенсивных потребителей. Потому что он будет считать, что при таком workload нам осталось еще немножко и мы выскачем, т. е. не системный процесс прибивать, а прибить что-то менее важное. Этим менее важным окажется интенсивный потребитель шаредной памяти, а именно postmaster. И после этого будет хорошо, если базу не придется восстанавливать.

Поэтому сейчас дефолтно, насколько я помню, большинство дистрибутивов – это где-то 6, т. е. в какой момент начинать использовать swap в зависимости от того, сколько памяти осталось. Мы сейчас советуем ставить vm.swapness = 1, потому что это практически его выключает, но не дает таких эффектов, как с неожиданно пришедшим OOM-killer’ом и все это дело прибившим.

Что дальше? Когда мы говорим о перфомансе баз данных и постепенно-постепенно походим к дискам, все начинают хвататься за голову. Потому что истина о том, что диск медленный и память быстрая, она всем с детства знакома. И все знают, что в базе данных будут проблемы с дисковой производительностью.

Основная проблема с производительностью PostgreSQL, связанная с checkpoints spikes, появляется не из-за того, что диск медленный. Это, скорее, от того, что пропускная способность памяти и диска не сбалансированы. При этом они могут быть не сбалансированными в разных местах. PostgreSQL не настроен, ОС не настроена, железо не настроено и железо неправильное. И этой проблемы не случается только в том случае, если все происходит как надо, т. е. либо нагрузки нет, либо настройки и железо хорошо подобранные.

Что это такое и как это выглядит? Обычно люди, которые с PostgreSQL работают в это дело вступали неоднократно. Я поясню. Как я говорил, PostgreSQL периодически делает checkpoints, чтобы грязные странички в шаредной памяти сдампить на диск. Если у нас большой объем шаредной памяти, то checkpoint начинает интенсивно воздействовать на диск, потому что дампит эти странички fsync. Он приезжает в kernel buffer и пишется на диски с помощью fsync. И если объем этого дела большой, то мы можем наблюдать неприятный эффект, а именно очень большую утилизацию дисков.

Здесь у меня есть две картинки. Я сейчас поясню, что это такое. Это два с коррелированных по времени графика. Первый график – это дисковая утилизация. Здесь она доходит почти до 90 % в этот момент времени. Если у вас выпад базы данных с физическими дисками, с RAID-контроллером утилизация под 90 %, то это плохие новости. Это значит, что еще чуть-чуть и наступит 100 и ввод-вывод остановится.

Если у вас дисковый массив, то там другая немножко история. Там зависит от того, как он настроен, что за массив и т. д.

А параллельно здесь сконфигурирован график из внутренней postgres’овой вьюхи, которая говорит, как происходит checkpoint. И зеленым цветом здесь показано, какое количество буферов, этих грязных страничек в этот момент приехало в этом checkpoint для синхронизации. И это главное, что здесь нужно знать. Мы видим, что у нас здесь много страничек приехало и в какой-то момент мы уперлись в плату, т. е. писали-писали, здесь явно дисковая система очень сильно занята. И у нас checkpoint очень сильно воздействует на диск. В идеале ситуация должна выглядеть, скорее, вот так, т. е. у нас здесь было меньше записи. И мы настройками можем это починить, чтобы дальше так было. Т. е. утилизация небольшая, но где-то что-то мы тут пишем.

Что нужно сделать, чтобы эту проблему победить? Если у вас остановилось IO под базой данных, то это значит, что все пользователи, которые пришли исполнять свои запросы, будут ждать.

Если посмотреть с точки зрения Linux, если вы взяли хороший hardware, правильно его настроили, нормально настроили PostgreSQL, чтобы он пореже делал эти checkpoints, размазывал их по времени друг между другом, то вы наступаете в дефолтные параметры Debian. Для большинства дистрибутивов Linux вот такая картина: vm.dirty_ratio=20, vm.dirty_background_ratio=10.

Что это значит? С ядра 2.6 появился один demon flushing’а. Pdglush в зависимости от того, кто какой использует, который занимается background’ным скидыванием грязных страничек из kernel buffer и скидыванием, когда надо во что бы не стало скидывать грязные странички, когда уже backgrouind’ное скидывание не помогает.

Когда наступает background? Когда 10 % от всей оперативной памяти, которая есть на сервере, занята грязными страничками в kernel buffer, то вызывается специальная функция списывания в background’е. Почему она background’ная? Она в качестве параметра принимает в себя, сколько страничек списать. И, допустим, списывает N страничек. И на какое-то время эта штука засыпает. И потом она снова приходит и списывает еще какое-то количество страничек.

Это предельно простая история. Тут задача как с бассейном, когда в одну трубу выливается, в другую вливается. У нас checkpoint пришел и если он мало грязных страничек отправил на скидывание, то постепенно из kernel buffer pgflush это все дело аккуратно рассосется.

Если продолжают накапливаться эти грязные странички, они накапливаются до 20 %, после этого в приоритете ОС все это дело списать на диск, потому что вылетит питание, и у нас все будет плохо. Мы потеряем эти данные, например.

В чем трюк? Трюк состоит в том, что вот эти параметры в современном мире 20 и 10 % от всей оперативной памяти, которая есть на машине, они совершенно чудовищны точки зрения пропускной способности любой дисковой системы, которая у вас есть.

Представьте себе, что у вас 128 GB оперативной памяти. 12,8 GB приезжают у вас в дисковую систему. И какой бы кэш у вас там не стоял, какой бы массив у вас там не стоял, они не выдержат столько.

Поэтому мы рекомендуем эти цифры сразу настраивать от возможности вашего RAID-контроллера. У меня сразу здесь дана рекомендация для контроллера, у которого 512 MB кэша.

Считается все очень просто. Можно vm.dirty_background в байтах поставить. И эти настройки отменяют предыдущие две. Либо ration по дефолту, либо активированы те, которые с байтами, то будут работать те, которые с байтами. Но поскольку я DBA-консультант и работаю с разными клиентами, я стараюсь стелить соломки и поэтому, если в байтах, то в байтах. Никто не дал никакой гарантии, что добрый админ не подсыплет памяти серверу, не перезагрузит его, а цифра останется той же. Просто рассчитывайте эти цифры, чтобы с гарантией все туда влезло.

Что произойдет, если вы не влезете? У меня написано, что эффективно останавливается любой flushing, но на самом деле это фигура речи. Операционная система имеет большую проблему – у нее много грязных страниц, поэтому останавливается эффективно тот IO, которые порождают ваши клиенты, т. е. пришло приложение sql-запрос отправить к базе, оно ждет. Любой ввод-вывод в нее – в самом низшем приоритете, потому что база занята checkpoint. И когда она его закончит совершенно непонятно. И когда вы достигли не фонового, не бэкграундного flushing’а, то это значит, что у вас все IO занято им. И пока оно не закончится, вы ничего не сделаете.

Тут есть еще два важных момента, которые выходят за рамки этого доклада. Вот этим настройкам должны матчится настройки в postgresql.conf, т. е. настройки checkpoints. И ваша дисковая система должна быть адекватно настроена. Если у вас есть кэш на RAID, то на нем должна быть батарейка. Люди покупают RAID с хорошим кэшом без батарейки. Если у вас SSD в RAID’ом, то они должны быть серверными, там должны быть конденсаторы. Тут развернутый чек-лист. По вот этой ссылке есть мой доклад про то, как настраивать диск перфоманс в PostgreSQL. Там все эти чек-листы есть.

Что еще очень сильно может усложнить жизнь? Это два параметра. Они относительно новые. Они по дефолту могут быть включены в разные приложения. И они могут осложнить жизнь ничуть не меньше, если они будут включены неправильно.

Есть две относительно новые штуки. Они уже в третьих ядрах появились. Это sched_migration_cost в наносекундах и sched_autogroup_enabled, который по дефолту один.

И как они портят жизнь? Что такое sched_migration_cost? У Linux scheduler может смигрировать процесс с одного CPU на другой. И для PostgreSQL, который выполняет запросы, миграция на другой CPU совершенно не понятна зачем. С точки зрения операционной системы, когда вы переключаете окна между openoffice и терминалом, то это, может быть, хорошо, но для базы данных – это очень плохо. Поэтому разумная политика – поставить migration_cost в какое-то большое значение, хотя бы несколько тысяч наносекунд.

Что это будет означать для scheduler? Будет считать, что на протяжении этого времени этот процесс все еще горячий. Т. е. если у вас какая-то долгая транзакция чем-нибудь долго занимается, что scheduler будет это понимать. Он будет считать, что пока не пройдет этот тайм-аут, то мигрировать этот процесс никуда не надо. Если при этом процесс что-то делает, то он не будет никуда смигрирован, он спокойно доработает на том CPU, который ему выделили. И результат получается отличный.

Второй момент – это autogroup. Есть хорошая идея для специфичных workload, не имеющих отношение к современным базам данных – это группировать процессы по тому виртуальному терминалу, из-под которого они запущены. Это удобно для каких-то задач. На практике PostgreSQL – это многопроцессная система с prefork’ом, которая запускается с одного терминала. У вас lock writer, checkpoint и все ваши клиентские запросы сгруппируются на один scheduler, на один CPU. И будут там дружно ожидать, когда он освободится, чтобы помешать друг другу и позанимать его подольше. Это история, которая совершенно не нужна в случае такой нагрузки и поэтому это нужно выключать.

Мой коллега Алексей Лесовский делал тесты с простым pgbench’ом, где увеличивал на порядок migration_cost и выключал autogroup. Разница на плохой железке получилась почти на 10 %. Есть обсуждение в postgres’овой рассылке, где люди приводят результаты, как подобные изменения на скорость запроса влияли на 50 %. Таких историй довольно много.

И напоследок про power saving policy. Хорошо, что теперь Linux можно использовать на ноутбуке. И он будет якобы хорошо расходовать батарейку. Но внезапно оказывается, что на сервере такое тоже может быть.

Боле того, если вы берете сервера в аренду у какого-нибудь хостера, то «добрые» хостеры не заботятся о том, чтобы у вас была производительность получше. Их задача сделать так, чтобы у них железо утилизировалось максимально эффективно. Поэтому они по умолчанию могут на операционной системе включить ноутбучный режим экономии энергии.

Если вы используете на сервере с базой данных под интенсивной нагрузкой вот это добро, то ваш выбор – это acpi_cpufreq + permormance. Даже с ondemand’ом уже будут проблемы.

Intel_pstate – уже немножко другой драйвер. И сейчас предпочтение отдается вот этому, как к более позднему и более хорошо работающему.

И, соответственно, governor только performance. Ondemand, powersave и все прочее – это не про вас.

Результаты по explain analyze PostgreSQL могут отличаться на несколько порядков, если вы включите powersave, потому что практически у вас под базой будет шедулиться CPU совершенно непредсказуемым способом.

Эти вещи могут быть включены по дефолту. Внимательно посмотрите – не включили ли они по дефолту. Это может быть действительно большой проблемой.

И в конце я хотел сказать спасибо ребятам из нашей DBA-команды PosgreSQL-Consulting, а именно Максу Богуку и Алексею Лесовскому, которые каждый день набивают на этом деле шишки. И для наших клиентов мы пытаемся сделать максимально хорошо, чтобы у них это все работало. Тут как с инструкциями по авиационной безопасности. Здесь все написано кровью. Каждая из этих гаек обнаружена в процессе какой-то проблемы. Я с радостью ими с вами делюсь.

Вопросы:

Спасибо! Если, например, компания хочет сэкономить и размещать на одном сервере базу данных и application логику или, если компания следует модной тенденции микросервисных архитектур, в которых PostgreSQL запускается в контейнере. В чем фишка? Sysctl глобально на все ядро аффектят. Я не слышал, чтобы sysctl как-то виртуализировались, чтобы они на контейнере по отдельности работали. Есть только cgroup и там только на часть есть контроль. Как это с этим можно жить? Или если хотите performance, то запускайте PostgreSQL на отдельном железном сервере и его тюньте?

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

В чем проблема? Если это виртуалка, то, скорее всего, у вас будет много проблем, например, с тем, что на большинстве виртуалок достаточно неконсистентная latency диска. Даже если пропускная способность дисков хорошая, то одна засбоившаяся транзакция операции ввода-вывода, не сильно влияющая на среднюю пропускную способность, которая случилась в момент checkpoint или в момент записи в WAL, то база от этого будет сильно страдать. И вы это заметите раньше, чем в эти проблемы упретесь.

Если у вас будет NGINX на том же самом сервере, то тоже будет та же самая проблема. Он будет драться за шаредную память. И до тех проблем, которые здесь описаны, вы не дойдете.

Но с другой стороны, некоторые из этих параметров все равно вам будут актуальны. Например, с sysctl поставить dirty_ration, чтобы был не такой безумный – в любом случае это поможет. Так или иначе у вас взаимодействие с диском будет. И оно будет по неправильной схеме. Это вообще дефолт те параметры, которые я показывал. И в любом случае их лучше поменять.

А с NUMA могут быть проблемы. VmWare, например, хорошо работает с NUMA с ровно противоположными настройками. И тут надо выбирать – железный сервер или не железный.

У меня вопрос, связанный с Amazon AWS. У них есть image преднастроенные. Один из них Amazon RDS называется. Есть ли там какие-то кастомные настройки для их операционной системы?

Там есть настройки, но это другие настройки. Здесь мы настраиваем операционную систему с точки зрения того, как база данных будет это дело использовать. А там есть параметры, которые определяют, куда идти нам сейчас, вот такой shaping. Т. е. нам нужно столько ресурсов, мы их сейчас будем выедать. После этого Amazon RDS эти ресурсы прикручивает, и там производительность падает. Есть отдельные истории, как люди начинают с этим делом химичить. Иногда даже довольно успешно. Но это не имеет отношение к настройкам ОС. Это как бы хакинг облака. Это другая история.

Почему Transparent huge pages не дают эффекта по сравнению с Huge TLB?

Не дают. Объяснить это можно многими способами. Но по факту они просто не дают его. Какая история у PostgreSQL? Он при старте выделяет большой кусок шаредной памяти. Transparent они при этом или не transparent – совершенно не важно. Тот факт, что они выделяются на старте, он объясняет все. И если памяти очень много и нужно перестраивать shared_memory segment, тогда Transparent huge pages будет актуален. У PostgreSQL он просто на старте выделен огромным куском и все, и дальше там ничего такого особенного не происходит. Можно, конечно, использовать, но есть шанс получить curruption shared_memory, когда он будет перевыделять что-нибудь. PostgreSQL же об этом не знает.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть