Optimization of a big PostgreSQL database

39
Оптимизация производительности большой унаследованной PostgreSQL базы Электропрохладительный кислотный тест Александр Чистяков, главный инженер Git in Sky, 2014

description

My presentation from Stachka'14 on PostgreSQL optimization

Transcript of Optimization of a big PostgreSQL database

Page 1: Optimization of a big PostgreSQL database

Оптимизация производительности большой унаследованной PostgreSQL

базы

Электропрохладительный кислотный тест

Александр Чистяков, главный инженер Git in Sky,

2014

Page 2: Optimization of a big PostgreSQL database

Кто я?

§ Меня зовут Саша§ Я инженер, главный инженер§ В компании Git in Sky§ Я люблю оптимизировать производительность§ Потому что это как волшебная сказка!

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 3: Optimization of a big PostgreSQL database

Где я? Кто вы?

§ Любите волшебные сказки?§ Пришли послушать про базу данных?§ Пришли послушать про оптимизацию производительности?§ Разрабатываете проекты для веб?§ Поддерживаете проекты в веб?§ У вас уже есть PostgreSQL?

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 4: Optimization of a big PostgreSQL database

О чем речь?

§ Доклад в жанре “field report”§ Если угодно - “trip report” (см. подназвание доклада)§ Предыстория: http://www.slideshare.net/profyclub_ru/08-6§ Однажды ко мне в дверь постучал

добрый волшебник§ И все заверте...

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 5: Optimization of a big PostgreSQL database

Краткое содержание предыдущих серий

§ Заказчик — конструктор сайтов http://setup.ru§ Пользовательский статический контент (файлы) хранится в

базе данных (PostgreSQL)§ Для больших файлов используются large objects§ Приложение на Perl, работает под Apache + mod_perl§ Переходим из 2012-го года в 2014-й, и...

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 6: Optimization of a big PostgreSQL database

Наше время

§ Было 6 миллионов файлов в базе — стало 207 миллионов (с версиями)/85 миллионов (без версий)

§ Времена, когда индексы были 2Gb, давно прошли§ Синхронизация тоже не 100 файлов в секунду, а в лучшем

случае 80, обычно — от 20 до 50§ База данных занимает на дисках ~6Tb§ И объем будет только расти

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 7: Optimization of a big PostgreSQL database

Почему не ...?

§ Россия — страна советов! (Каждый суслик — агроном!)§ “Работает — не трогай” (на самом деле, нет, но)§ У решений могут быть бизнес-причины§ TIMTOWTDI! (Кстати, Perl же!)§ Один из путей — “долго и дорого”

(“никогда и дорого”?)§ Вывод очевиден?

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 8: Optimization of a big PostgreSQL database

Все же, почему не ...?

§ OpenStack Swif§ Elliptics§ Ceph, MogileFS, MooseFS, whatever§ Слово “кислотный” из подзаголовка (Atomicity, Consistency, etc)

§ Либо делать групповую транзакцию в бизнес-логике (переписать всё приложение)

§ Либо транзакции берет на себя хранилище^ Много ли мы знаем таких хранилищ?

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 9: Optimization of a big PostgreSQL database

Объекты предметной области и базы

§ Таблица domains — содержит имена доменов, пример — setup.ru

§ Таблица content — содержит метаинформацию о файле (время последнего изменения, на основании которого принимается решение об актуальности бинарных данных)

§ Таблица stat — содержит собственно сами бинарные данные и их sha1-хэш (дедупликация!)

§ Таблица deleted — содержит признак того, что файл был удален§ Итого, у нас есть четыре связанных между собой таблицы

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 10: Optimization of a big PostgreSQL database

Пользовательские сценарии

§ Публикация и синхронизация файлов:§ Публикуем изменения всегда на одну и ту же ноду§ Иначе пользователь будет видеть старый контент§ Кастомный синхронизатор не очень быстро

распространяет изменения на все узлы§ Отдача статического контента:

§ Нужно отдавать а) последнюю, б) неудаленную версию

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 11: Optimization of a big PostgreSQL database

Что не очень хорошо?

§ Отдача работает не очень быстро§ Публикация и синхронизация работают не очень быстро§ Существующее железо справляется не очень хорошо§ Пара слов о железе:

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 12: Optimization of a big PostgreSQL database

Полный Хетцнер!

§ Исходно — RAID0 на 2*3Tb SATA диска, 16G RAM, RAID1 на 2 SSD для pg_temp и временных файлов nginx — сортировка и объединение таблиц в PostgreSQL и буферизация в nginx работают быстро

§ Переезд на RAID10 4*4Tb SATA диска (стало не хватать места), 48G RAM

§ Несмотря на наличие технической возможности, поставить SSD под кэш или временные файлы больше нельзя — добро пожаловать в Хетцнер!

§ ^ Надо как-то жить с этим

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 13: Optimization of a big PostgreSQL database

Есть ли у вас план, мистер Фикс?

§ Как это делается обычно:§ slow queries log§ pgFouine или pgBadger§ Раз в сутки (или даже чаще) — красивый рейтинг «плохих»

запросов статистика с победителями§ Смотрим план (опять это слово!) запроса§ Кто знает, что такое “план запроса”?§ Кто не знает — тот тоже оптимизатор

(но поисковый)

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 14: Optimization of a big PostgreSQL database

За спичками

§ Дело не выглядит сложным, кстати:§ “Найти неудаленный файл” при отдаче - это запрос к

view§ “Найти данные для синхронизации” - это тоже запрос к

view§ Это самые распространенные запросы§ Их планы и надо смотреть и оптимизировать

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 15: Optimization of a big PostgreSQL database

And the Oscar goes to...

§ А вот и план, о котором мы так долго говорили:§

§

§

§

§

§ Что-то он какой-то большой

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 16: Optimization of a big PostgreSQL database

Чрезвычайные и срочные меры

§ Материализовать нематериализованный view!§ PostgreSQL 9.2 — нет “родной” поддержки materialized view§ ^ не беда§ В книге “Enterprise Rails” отлично описано, как эмулировать

materialized view при помощи триггеров§ BTW WTF is “Enterprise Rails”?§ У нас опять есть план — чего же мы ждем?

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 17: Optimization of a big PostgreSQL database

Кстати, как это работает?

§ Буквально в двух словах (explain to me like I'm five years old):§ “Поверх” нематериализованного view делается таблица

с такими же полями§ Она работает как кэш — записи в ней создаются по

запросу§ Сначала идем в эту таблицу, потом во view, если там не

нашлось§ Записи инвалидируется при помощи триггеров на всех

таблицах-участниках исходного view

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 18: Optimization of a big PostgreSQL database

Все сделал как в книге!

§ Надо как-то проверить, что все удалось?§ Честно скажу, pgBadger и pgFouine я не трогал вообще§ Потому что slow log нерепрезентативен и не отражает динамику§ Расширение pg_stat_statements§ ^ должно быть включено у всех без исключения

на планете Земля§ Позволяет смотреть статистику в реальном времени

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 19: Optimization of a big PostgreSQL database

pg_stat_statements

§ SELECT

(total_time / 1000 / 60) as total_minutes,

(total_time/calls) as average_time,

calls, query

FROM pg_stat_statements

ORDER BY total_minutes/average_time desc;

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 20: Optimization of a big PostgreSQL database

pg_stat_statements

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 21: Optimization of a big PostgreSQL database

Вскрытие показало

§ Кэширующая таблица действительно работает§ Примерно 30-40% запросов не попадает в кэш§ ^ Хорошо, надо подождать§ На второй день ожидания ситуация не изменилась

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 22: Optimization of a big PostgreSQL database

Знай и люби бизнес-логику!

§ Алгоритм:§ Посмотреть в таблице§ Посмотреть в исходном view (долго)

§ А что, если такого файла вообще нет?§ 30-40 процентов запросов — к файлам, которых вообще

нет§ Зачем ходить во view за ними?

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 23: Optimization of a big PostgreSQL database

Наступило утро, проснулся комиссар

§ Ночью — 15 миллисекунд в среднем§ Днем — 40-50 миллисекунд в среднем§ Вносить изменения лучше ночью§ Но результат будет известен только в середине дня!

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 24: Optimization of a big PostgreSQL database

Наступило утро, проснулся комиссар

§ Ночью — 15 миллисекунд в среднем§ Днем — 40-50 миллисекунд в среднем§ Вносить изменения лучше ночью§ Но результат будет известен только в середине дня!

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 25: Optimization of a big PostgreSQL database

Возвращение целесообразности

§ Наша главная метрика — время отдачи контента пользователю!

§ При чем тут pg_stat_statements?§ Zabbix§ Graphite/StatsD§ https://github.com/alexclear/ansible-graphite-playbook

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 26: Optimization of a big PostgreSQL database

Мониторинг/графики

Мониторинг нормального человека Мониторинг курильщика

Zabbix Cacti, Munin+NAGIOS

StatsD/Graphite Riemann+Collectd

NAGIOS passive checks

Мониторинг алкоголика Мониторинг наркомана

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 27: Optimization of a big PostgreSQL database

Мониторинг/графики

Мониторинг нормального человека Мониторинг курильщика

Zabbix Cacti, Munin+NAGIOS

StatsD/Graphite Riemann+Collectd

NAGIOS passive checks

Мониторинг алкоголика Мониторинг наркомана

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 28: Optimization of a big PostgreSQL database

Еще пара слов про Zabbix

§ ВоронКаркнул:НИКОГДА!

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 29: Optimization of a big PostgreSQL database

Ogres have layers

§ Graphite/StatsD stack:§ Dashboard (тысячи их, я просто взял стандартный, он

плох)§ Веб-интерфейс отдачи графиков (на Django)§ Collector w/RRD-like storage (Carbon)§ Aggregator/preprocessor w/UDP interface (StatsD)

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 30: Optimization of a big PostgreSQL database

StatsD implementation

§ На Go, Node.JS, Python, Perl, C, ... (тысячи их)§ Сначала я взял Python:

§ ^ Автобус не придет§ Старый добрый Perl!

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 31: Optimization of a big PostgreSQL database

Покой нам только снится

§ Снится не покой, а те самые 40-50 миллисекунд, которые не хотят уменьшаться

§ Что делать?§ Как обычно, построить более подходящие индексы

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 32: Optimization of a big PostgreSQL database

Момент истины

§ Для самого частого запроса построен хороший индекс на три столбца (до того был — на два столбца, а исходно был на один столбец)

§ В этот момент все стало еще хуже :)§ Размер индекса — 18 гигабайт§ Все предыдущие докладчики, наверняка, говорили, что

маленький индекс лучше, чем большой

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 33: Optimization of a big PostgreSQL database

One size does not fit all

§ Один из столбцов, по которому построен индекс — varchar§ Превращаем varchar в int:§ http://stackoverflow.com/a/9812029/601572§ create function h_int(text) returns int as $$

select ('x'||substr(md5($1),1,8))::bit(32)::int;

$$ language sql;§ Забыл сказать — я не боюсь хранимых процедур и триггеров

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 34: Optimization of a big PostgreSQL database

После шлифовки отполировать

§ SET enable_bitmapscan=false; <= старые добрые nested loops

SELECT something

FROM stat s JOIN domains d ON d.id = s.domain JOIN content c ON c.id = s.content

LEFT JOIN deleted e ON e.id = s.id

WHERE d.name = domname

AND h_int(s.name) = h_int(filename <= работает новый маленький индекс

AND s.name = filename

AND date_part('epoch'::text, s.ptime) = filerev

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 35: Optimization of a big PostgreSQL database

Начинаем спать по ночам

§ Индекс занимал 18 гигабайт, стал занимать 8 гигабайт§ Среднее время выполнения запроса днем в моменты

пиковой нагрузки было 40-50 миллисекунд, стало 20-25 миллисекунд

§ 90% запросов обслуживаются за 100 миллисекунд (время от момента начала обработки запроса Perl-приложением до момента конца обработки, включает все SQL-запросы)

§ В среднем запрос обслуживается приложением за 50 мс

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 36: Optimization of a big PostgreSQL database

Мы строили-строили, и, наконец...

§ ...и, наконец:

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 37: Optimization of a big PostgreSQL database

Zabbix strikes back

§ ...и, наконец:

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 38: Optimization of a big PostgreSQL database

Выводы:

§ «Теория малых дел», внезапно, работает^ несмотря на свой почтенный возраст

§ Ломать — не строить!§ Знание — сила!§ Учение Маркса всесильно, потому что оно

верно!§ Кажется, я не туда пишу...§ В планах — шардинг, да

Оптимизация производительности большой унаследованной PostgreSQL базы. 2014

Page 39: Optimization of a big PostgreSQL database

С вами был Александр Чистяков,главный инженер Git in Sky

[email protected]://gitinsky.com

http://meetup.com/DevOps-40

Пожалуйста, ваши вопросы.

Спасибо за понимание!