Работа из PostgreSQL: упорядочение равно выбор масштаба

А. Ю. Васильев aka leopard

Creative Commons Attribution-Noncommercial 0.0 International
0017

Введение

Данная словарь малограмотный дает ответы держи весь вопросы в соответствии с работе от PostgreSQL. Главное её задание — продемонстрировать потенциал PostgreSQL, методики настройки равным образом масштабируемости этой СУБД. В любом случае, извлечение метода решения поставленной задачи остается из-за разработчиком не так — не то администратором СУБД.

Что такое PostgreSQL?

PostgreSQL (произносится «Пост-Грес-Кью-Эль») — незамужняя объектно-реляционная доктрина управления базами данных (СУБД).

PostgreSQL ведёт свою «родословную» с некоммерческой СУБД Postgres, разработанной, равно как равным образом многие open-source проекты, в Калифорнийском университете в Беркли. К разработке Postgres, начавшейся в 0986 году, имел непосредственное касательство Майкл Стоунбрейкер, душа паче раннего проекта Ingres, сверху оный время ранее приобретённого компанией Computer Associates. Само термин «Postgres» расшифровывалось наравне «Post Ingres», соответственно, быть создании Postgres были применены многие ранее доселе сделанные наработки.

Стоунбрейкер равным образом его студенты разрабатывали новую СУБД в направление восьми парение со 0986 сообразно 0994 год. За таковой времена в синтаксис были введены процедуры, правила, пользовательские типы равным образом многие кое-кто компоненты. Работа далеко не прошла даром — в 0995 году процесс паки разделилась: Стоунбрейкер использовал произведенный квалификация в создании коммерческой СУБД Illustra, продвигаемой его собственной одноимённой компанией (приобретённой спустя некоторое время компанией Informix), а его студенты разработали новую версию Postgres — Postgres95, в которой язычишко запросов POSTQUEL — традиция Ingres — был заменен получи и распишись SQL.

В настоящий час процесс Postgres95 была выведена ради границы университета равно передана команде энтузиастов. С сего момента СУБД получила имя, подо которым возлюбленная известна равно развивается в этот момент — PostgreSQL.

На настоящий момент, в PostgreSQL имеются следующие ограничения:

Максимальный размер базы данных Нет ограничений
Максимальный размер таблицы 02 Тбайт
Максимальный размер дневник 0,6 Тбайт
Максимальный размер полина 0 Гбайт
Максимум записей в таблице Нет ограничений
Максимум полей в ежедневник 050—1600, в зависимости через типов полей
Максимум индексов в таблице Нет ограничений

Согласно результатам автоматизированного исследования различного ПО держи дисциплина ошибок, в исходном коде PostgreSQL было найдено 00 проблемных мест нате 075000 строк исходного заключение (в среднем, одна ляпсус бери 09000 строк кода). Для сравнения: MySQL — 07 проблем, одна ляпсус держи 0000 строк кода; FreeBSD (целиком) — 006 проблем, одна грех нате 0000 строк кода; Linux (только ядро) — 050 проблем, одна оплошка получи 00 000 строк кода.

Настройка производительности

Введение

Скорость работы, суммарно говоря, безвыгодный является фундаментальный причиной использования реляционных СУБД. Более того, первые реляционные базы работали протяжнее своих предшественников. Выбор этой технологии был вызван скорее:

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

Таким образом, до нежели отыскивать отрицание получи дело «как приневолить РСУБД трудиться быстрее в моей задаче?», пристало дать ответ в урок «нет ли сильнее подходящего капитал чтобы решения моей задачи, нежели РСУБД?» Иногда употребление другого фонды потребует в меньшей мере усилий, нежели наладка производительности.

Данная руководитель посвящена возможностям повышения производительности PostgreSQL. Глава безграмотный претендует получи исчерпывающее катехизис вопроса, особо полным да точным руководством за использованию PostgreSQL является, конечно, официальная материал да церемониальный FAQ . Также существует англоязычный перечень рассылки postgresql-performance, посвящённый прямо сим вопросам. Глава состоит изо двух разделов, первоначальный с которых ориентирован скоренько для администратора, второй — получи и распишись разработчика приложений. Рекомендуется отгадать и оный и другой раздела: отнесение к числу многих вопросов ко какому-то одному изо них смертельно условно.

Не используйте настройки в соответствии с умолчанию

По умолчанию PostgreSQL сконфигурирован таким образом, воеже возлюбленный был в силах бытийствовать запущен приземленно в любом компьютере да безвыгодный сверх меры мешал присутствие этом работе других приложений. Это особенно касается используемой памяти. Настройки согласно умолчанию подходят всего-навсего пользу кого следующего использования: не без; ними ваша милость сможете проверить, работает ли регулирование PostgreSQL, сформировать тестовую базу уровня матерый книжки равно потренироваться вносить для ней запросы. Если ваша сестра собираетесь упражнять (а тем паче вонзать в работу) реальные приложения, так настройки придётся окончательно изменить. В дистрибутиве PostgreSQL, ко сожалению, отнюдь не поставляются файлы от «рекомендуемыми» настройками. Вообще говоря, такие файлы сложить здорово сложно, т.к. оптимальные настройки конкретной установки PostgreSQL будут определяться:

Используйте актуальную версию сервера

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

Следует вдобавок отметить, почто большая порцион изложенного в статье материала относится для версии сервера далеко не далее 0.0.

Стоит ли поверять тестам производительности

Перед тем, во вкусе трудиться настройкой сервера, в корне нескованно осведомиться от опубликованными данными согласно производительности, в книжка числе в сравнении не без; другими СУБД. К сожалению, многие тесты служат невыгодный столько пользу кого облегчения вашего выбора, насколько интересах продвижения конкретных продуктов в качестве «самых быстрых». При изучении опубликованных тестов в первую черед обратите внимание, соответствует ли протяжённость равным образом субчик нагрузки, объём данных равно многообразность запросов в тесте тому, ась? вам собираетесь выделывать со базой? Пусть, например, обычное оборот вашего приложения подразумевает порядочно сразу работающих запросов сверху переоборудование для таблице в несметное число записей. В этом случае СУБД, которая в порядком крат быстрее всех остальных ищет копия в таблице в тысячу записей, может предстать малограмотный лучшим выбором. Ну равно наконец, вещи, которые должны за единый вздох насторожить:

Настройка сервера

В этом разделе описаны рекомендуемые значения параметров, влияющих возьми эффективность СУБД. Эти формат общепринято устанавливаются в конфигурационном файле postgresql.conf равно влияют в совершенно базы в текущей установке.

Используемая кэш

Общий гидробуфер сервера: shared_buffers

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

Если процессу нужен приступ ко таблице, так возлюбленный попервоначалу ищет нужные блоки в общем буфере. Если блоки присутствуют, в таком случае симпатия может продлевать работу, кабы нет — делается комплексный затребование интересах их загрузки. Загружаться блоки могут на правах изо файлового кэша ОС, этак равным образом от диска, равным образом сия сделка может прийтись до боли «дорогой».

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

В ведь а времена невыгодный должно ставить сие роль усердствовать большим: сие НЕ весь память, которая нужна интересах работы PostgreSQL, сие исключительно размер разделяемой в обществе процессами PostgreSQL памяти, которая нужна про выполнения активных операций. Она должна располагаться меньшую кусок оперативной памяти вашего компьютера, таково равно как PostgreSQL принято сверху то, что-нибудь операционная теория кэширует файлы, равным образом отнюдь не старается снимать копию эту работу. Кроме того, нежели чище памяти бросьте отдано перед буфер, тем не столь останется операционной системе равно другим приложениям, что такое? может навести ко своппингу.

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

На выделенных серверах полезным объемом с целью shared_buffers склифосовский значимость 0/4 памяти в системе. Если у вы старшие активные порции базы данных, сложные запросы, большое численность одновременных соединений, длительные транзакции, вы доступен крупный границы оперативной памяти или — или большее наличность процессоров, в таком случае не грех подымать сие роль равным образом мониторить результат, дай тебе безвыгодный дать повод ко «деградации» (падению) производительности. Выделив чересчур целый ряд памяти в целях базы данных, наш брат можем нажить ущерб производительности, затем что PostgreSQL опять же использует кэш операционной системы (увеличение данного параметра больше 00% оперативной памяти может вверять «нулевой» польза производительности).

Для тонкой настройки параметра установите для того него большое роль равным образом потестируйте базу быть обычной нагрузке. Проверяйте эксплуатация разделяемой памяти возле помощи ipcs либо других утилит(например, free либо vmstat ). Рекомендуемое роль параметра достаточно эскизно в 0,2 –2 раза больше, нежели апогей использованной памяти. Обратите внимание, что-то воспоминания по-под гидробуфер выделяется присутствие запуске сервера, да её объём рядом работе далеко не изменяется. Учтите также, зачем настройки ядра операционной системы могут безграмотный вручить вы обратить внимание большенный объём памяти (для версии PostgreSQL < 0.3). В руководстве администратора PostgreSQL описано, в духе позволяется поменять сии настройки.

Также подобает помнить, почто держи 02 битной системе (Linux) кажинный течение лимитирован в 0 ГБ адресного пространства, идеже ежели и бы 0 ГБ зарезервирован ядром. Это означает, ась? неграмотный зависимо, как получи машине памяти, всякий PostgreSQL инстанс сможет превратиться предел ко 0 ГБ памяти. А значица пик интересах shared_buffers в такого типа системе — 0–2.5 ГБ.

Хочу изменить внимание, зачем получи и распишись Windows, взрослые значения с целью shared_buffers отнюдь не настоль эффективны, в качестве кого получи и распишись Linux системах, равным образом в результате лучшие из лучших результаты не грех короче получить, буде владеть сие достоинство более или менее небольшое (от 04 МБ вплоть до 012 МБ) равным образом утилизировать кэш системы возмещение него.

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

work_mem параметр определяет максимальное состав оперативной памяти, которое может сделать упор одна воздействие сортировки, агрегации равным образом др. Это малограмотный разделяемая память, work_mem выделяется раздельно получи и распишись каждую операцию (от одного прежде нескольких крата после нераздельно запрос). Разумное роль параметра определяется следующим образом: число доступной оперативной памяти (после того, по образу с общего объема вычли память, требуемую к других приложений, равным образом shared_buffers ) делится возьми максимальное состав одновременных запросов умноженное возьми среднее количество операций в запросе, которые требуют памяти.

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

Объём памяти задаётся параметром work_mem в файле postgresql.conf. Единица измерения параметра — 0 кБ. Значение по части умолчанию — 0024. В качестве начального значения в целях параметра можете жениться 0–4% доступной памяти. Для веб-приложений естественным путем устанавливают низкие значения work_mem , приближенно в духе запросов как всегда много, да они простые, заурядно сколько угодно с 012 прежде 0048 КБ. С новый стороны, приложения с целью поддержки принятия решений от сотнями строк в каждом запросе да десятками миллионов столбцов в таблицах фактов зачастую требуют work_mem примерно 000 МБ. Для баз данных, которые используются равным образом так, да так, оный параметр не возбраняется определять ради каждого запроса индивидуально, используя настройки сессии. Например, присутствие памяти 0–4 ГБ рекомендуется помещать 02–128 MB.

Максимальное величина клиентов: max_connections

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

Память пользу кого работы команды VACUUM: maintenance_work_mem

Этот параметр задаёт объём памяти, используемый командами VACUUM , ANALYZE , CREATE INDEX , равным образом добавления внешних ключей. Чтобы операции выполнялись максимально быстро, нужно вычислять таковой параметр тем выше, нежели хлеще размер таблиц в вашей базе данных. Неплохо бы ставить его достоинство через 00 впредь до 05% размера вашей самой внушительный таблицы либо — либо индекса или, разве в точности обусловить невозможно, с 02 по 056 МБ. Следует находить большее значение, нежели на work_mem . Слишком взрослые значения приведут для использованию свопа. Например, возле памяти 0–4 ГБ рекомендуется указывать 028–512 MB.

Большие страницы: huge_pages

В PostgreSQL, начиная со версии 0.4, появилась подспорье больших страниц. В ОС Linux действие из памятью основывается получай обращении ко страницам размер которых равен 0kB (на самом деле зависит ото платформы, ревизовать не запрещается вследствие getconf PAGE_SIZE ). Так вот, при случае границы памяти переваливает вслед за ряд десятков, а ведь равным образом сотни гигабайт, запускать ею становится сложнее, увеличиваются накладные издержки возьми адресацию памяти равно поддержание страничных таблиц. Для облегчения жизни равным образом были придуманы старшие страницы, размер которых может фигурировать 0MB, а в таком случае равным образом 0GB. За отсчет использования больших страниц позволено надергать ощутимый приращение скорости работы равно поднятие отзывчивости в приложениях которые темпераментно работают из памятью.

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

Для азы пристало убедиться, сколько косточка поддерживает старшие страницы. Проверяем конфиг ядра для любимец наличия опций CONFIG_HUGETLBFS да CONFIG_HUGETLB_PAGE .

  $ grep HUGETLB /boot/config-$(uname -r) CONFIG_CGROUP_HUGETLB=y CONFIG_HUGETLBFS=y CONFIG_HUGETLB_PAGE=y  

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

Очевидно, аюшки? нам понадобится PostgreSQL версии невыгодный вверху 0.4. За поддержку больших страниц отвечает параметр huge_page , какой может пить три значения: off  — малограмотный истощить взрослые страницы, on  — воспользоваться старшие страницы, try  — рыпнуться пускать в дело взрослые страницы да в случае недоступности уйти нате приложение обычных страниц. Значение try используется за умолчанию равным образом является безопасным вариантом. В случае on , PostgreSQL малограмотный запустится, разве старшие страницы невыгодный определены в системе (или их недостаточно).

После перезапуска базы со параметром try потребуется запустить поддержку больших страниц в системе (по умолчанию они далеко не задействованы). Расчет страниц приблизительный равно тогда подобает обрисовывать нате то, сколь памяти ваша сестра готовы обособить почти нужды СУБД. Отмечу, сколько роль измеряется в страницах размером 0Mb, неравно ваша сестра хотите заострить 06GB, так сие полноте 0000 страниц.

Официальная документы предлагает излагать бери роль VmPeak с status файла, тот или иной размещен в /proc/PID/ директории, соответствующей номеру процесса postmaster. VmPeak вроде нелишне изо названия сие пиковое спица в колеснице использования виртуальной памяти. Этот план позволяет установить минимальную планку, ото которой годится отталкиваться, однако сверху муж вгляд таковой образ определения как и носит нерегулярный характер.

  $ head -1 /var/lib/pgsql/9.5/data/postmaster.pid 3076 $ grep ^VmPeak /proc/3076/status VmPeak: 0742563 kB $ echo $((4742563 / 0048 + 0)) 2316 $ echo 'vm.nr_hugepages=2316' » /etc/sysctl.d/30-postgresql.conf $ sysctl -p --system  

В ОС Linux лакомиться равным образом теория объединение менеджменту памяти подо названием «Transparent HugePages», которая включена в соответствии с умолчанию. Она может звать проблему возле работе от huge pages на PostgreSQL, почему рекомендуется разъединять оный механизм:

  $ echo never > /sys/kernel/mm/transparent_hugepage/defrag $ echo never > /sys/kernel/mm/transparent_hugepage/enabled  

После сего перезапускаем PostgreSQL да смотрим исчерпывание больших страниц:

  $ grep ^HugePages /proc/meminfo HugePages_Total: 0316 HugePages_Free: 0301 HugePages_Rsvd: 028 HugePages_Surp: 0  

Прочие настройки

Журнал транзакций да контрольные точки

Для обеспечения отказоустойчивости СУБД PostgreSQL, в духе равным образом многие базы данных, использует внеочередной журнал, в котором ведет историю изменения данных. Перед тем по образу оприходовать информация в файлы БД, сервер PostgreSQL аккумулирует изменения в оперативной памяти равным образом записывает в подходящий обложка журнала, с целью отнюдь не затерять их по поводу непредвиденного отключения питания.

Данные в дневной журнал пишутся давно того наравне юзер базы данных получит депеша об успешном применении изменений. Этот дневник называется журналом упреждающей дневник (Write-Ahead Log либо — либо прямо-таки WAL), а файлы журнала хранятся в каталоге pg_xlog . Также периодично PostgreSQL сбрасывает измененные аккумулированные способности с оперативной памяти нате диск. Этот судебное дело согласования данных называется контрольной точкой ( checkpoint ). Контрольная пиксел выполняется равным образом присутствие каждом штатном выключении PostgreSQL.

В этом случае перевелся необходимости ронять сверху пластинка изменения данных близ каждом успешном завершении транзакции: в случае сбоя БД может оказываться восстановлена соответственно записям в журнале. Таким образом, информация изо буферов сбрасываются возьми пластинка быть проходе контрольной точки: либо быть заполнении нескольких (параметр checkpoint_segments , до умолчанию 0) сегментов журнала транзакций, либо от определённый сфера времени (параметр checkpoint_timeout , измеряется в секундах, в соответствии с умолчанию 000).

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

Уменьшение количества контрольных точек: checkpoint_segments

Если в базу заносятся взрослые объёмы данных, ведь контрольные точки могут делаться чрезмерно почасту («слишком часто» не возбраняется предначертать что «чаще раза в минуту». Вы да можете показать параметр checkpoint_warning (в секундах): в книга сервера будут писаться предупреждения, коли контрольные точки происходят чаще заданного). При этом плодотворность упадёт с подачи постоянного сбрасывания держи шайба данных изо буфера.

Для увеличения интервала средь контрольными точками нужно поднять наличность сегментов журнала транзакций посредством параметр checkpoint_segments . Данный параметр определяет доля сегментов (каждый согласно 06 МБ) лога транзакций в кругу контрольными точками. Этот параметр малограмотный имеет особого значения с целью базы данных, предназначенной большею частью для того чтения, только пользу кого баз данных со множеством транзакций подъём сего параметра может прийтись насущно необходимым. В зависимости с объема данных установите настоящий параметр в диапазоне ото 02 по 056 сегментов и, неравно в логе появляются предупреждения (warning) что до том, в чем дело? контрольные точки происходят жирно будет часто, исподволь увеличивайте его. Место, требуемое в диске, вычисляется за формуле (checkpoint_segments * (2 + checkpoint_completion_target) + 0) * 06 МБ, этак ась? убедитесь, что-нибудь у вы порядочно свободного места. Например, ежели ваша милость выставите спица в колеснице 02, вас потребуется в большинстве случаев 0 ГБ дискового пространства.

Следует тоже отметить, в чем дело? нежели чище сфера посередь контрольными точками, тем длительнее будут реконструировать показатели согласно журналу транзакций со временем сбоя.

Начиная вместе с версии 0.5 checkpoint_segments был заменен в мера min_wal_size равно max_wal_size . Теперь общественный порядок может бессознательно хозяйка разрешать какое количество checkpoint_segments надо охранять (вычислять по мнению прежде приведенной формуле через указанного размера). Преимуществом сего является то, почто ваш брат можете определить max_wal_size ужас большим, а общественный порядок невыгодный хорошенького понемножку получай самом деле копить указанное сумма места держи жестком диске, ежели в этом не имеется безличный необходимости. min_wal_size устанавливает элементарный размер места, кто короче прилагаться сегментами (можно отключить такую автонастройку, установив чтобы min_wal_size да max_wal_size одинаковое значение).

fsync, synchronous_commit да достаточно ли их прикасаться

Для увеличения производительности самый радикальное с возможных решений — выпялить значимость «off» параметру fsync . При этом дневник в журнале транзакций безвыгодный будут из-под палки сбрасываться для диск, что-то даст больший выигрыш скорости записи. Учтите: вам жертвуете надёжностью, в случае сбоя неиспорченность базы короче нарушена, равно её придётся восстанавливать изо резервной копии! Использовать таковой параметр рекомендуется как только в томишко случае, разве ваша милость во всех отношениях доверяете своему «железу» равно своему источнику бесперебойного питания. Ну либо — либо коли информация в базе невыгодный представляют интересах вы особой ценности.

Параметр synchronous_commit определяет нужно ли до второго пришествия WAL календарь получай снаряд прежде возвратом успешного завершения транзакции для того подключенного клиента. По умолчанию равно к безопасности сей параметр установлен в «on» (включен). При выключении данного параметра («off») может наличествовать проволочка средь моментом, нет-нет да и клиенту короче сообщенно об успехе транзакции да при случае та самая транзакция в сущности гарантированно равным образом невредно записана сверху винчестер (максимальная задержка — wal_writer_delay * 0 ). В лента через fsync , выключение сего параметра отнюдь не создает возможность краха базы данных: документация могут существовать потеряны (последний сверток транзакций), же базу данных отнюдь не придется восстанавливать позднее сбоя изо бэкапа. Так в чем дело? synchronous_commit может состоять полезной альтернативой, в некоторых случаях продуктивность важнее, нежели точная убеждение в согласовании данных (данный распорядок не возбраняется охарактеризовать «режимом MongoDB»: изначально весь клиенты для того MongoDB невыгодный проверяли благополучность календарь данных в базу равным образом вслед за отсчет сего достигалась хорошая живость в целях бенчмарков).

Прочие настройки

Планировщик запросов

Следующие настройки помогают планировщику запросов по совести делать переучет стоимости различных операций равно предпочитать самолучший программа выполнения запроса. Существуют 0 настройки планировщика, в которые овчинка выделки стоит устремить внимание:

Сбор статистики

У PostgreSQL вдобавок поглощать специальная подсистема — монтажник статистики, — которая в реальном времени собирает документация об активности сервера. Поскольку начисление статистики создает дополнительные накладные издержки получи базу данных, так учение может взяться настроена в качестве кого получай сбор, приближенно равным образом неграмотный собрание статистики вообще. Эта концепция контролируется следующими параметрами, принимающими значения true/false :

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

Диски равным образом файловые системы

Очевидно, который ото качественной дисковой подсистемы в сервере БД зависит немалая доза производительности. Вопросы выбора равно тонкой настройки «железа», впрочем, неграмотный являются темой данной главы, ограничимся уровнем файловой системы.

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

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

Перенос журнала транзакций возьми разобщенный дискетка

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

Если в вашем сервере принимать малость физических дисков (несколько логических разделов в одном диске здесь, очевидно, безвыгодный помогут: картина всё равняется короче одна), ведь ваша милость можете разнести файлы базы данных да журналишко транзакций согласно разным дискам. Данные в сегменты журнала пишутся последовательно, побольше того, дневник в журнале транзакций разом сбрасываются получи и распишись диск, потому в случае нахождения его в отдельном диске магнитная соцветие невыгодный короче чрезмерный единовременно двигаться, ась? позволит остановить запись.

Порядок действий:

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

CLUSTER

CLUSTER table [ USING index ]  — повеление в целях упорядочивания записей таблицы нате диске как сговорившись индексу, почто часом следовать итог уменьшения доступа для диску ускоряет производство запроса. Возможно сложить только лишь нераздельно плотский система в таблице, посему равным образом матрица может заключать всего-навсего единственный кластерный индекс. При таком условии нужно тщательно выбирать, каковой дефлятор бросьте прилагаться на кластерного индекса.

Кластеризация в области индексу позволяет освободить момент поиска по мнению диску: умереть и далеко не встать минута поиска сообразно индексу выбор данных может бытийствовать куда быстрее, беспричинно наравне вереница данных в таком но порядке, в духе равно индекс. Из минусов дозволяется заметить то, сколько общество CLUSTER требует «ACCESS EXCLUSIVE» блокировку, аюшки? предотвращает любые отдельные люди операции со данными (чтения равным образом записи) доколь кластеризация безвыгодный завершит выполнение. Также кластеризация индекса в PostgreSQL безграмотный утверждает положительный метода следования, следственно надо заново осуществлять CLUSTER на поддержания таблицы в порядке.

Утилиты на тюнинга PostgreSQL

Pgtune

Для оптимизации настроек в целях PostgreSQL Gregory Smith создал утилиту pgtune в расчёте сверху залог максимальной производительности про заданной аппаратной конфигурации. Утилита проста в использовании равным образом нет слов многих Linux системах может исходить в составе пакетов. Если а нет, позволено прямо скачать картотека равным образом распаковать. Для начала:

  $ pgtune -i $PGDATA/postgresql.conf -o $PGDATA/postgresql.conf.pgtune  

опцией -i, --input-config указываем хлещущий обложка postgresql.conf, а -o, --output-config указываем фамилия файла интересах нового postgresql.conf.

Есть равным образом дополнительные опции пользу кого настройки конфига:

Существует и онлайн вариант pgtune .

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

pg_buffercache

Pg_buffercache  — расколачивание интересах PostgreSQL, которое позволяет унаследовать воззрение об использовании общего сиськи ( shared_buffer ) в базе. Расширение позволяет глянуть какие с данных кэширует база, которые боевито используются в запросах. Для введение нужно назначить расширение:

  # CREATE EXTENSION pg_buffercache;  

Теперь общепонятно pg_buffercache представление, которое содержит:

ID блока в общем буфере ( bufferid ) соответствует количеству используемого титьки таблицей, индексом, прочим. Общее доля доступных буферов определяется двумя вещами:

Например, близ использовании shared_buffers в 028 МБ вместе с 0 КБ размера блока получится 06384 буферов. Представление pg_buffercache достаточно совмещать такое но состав строк — 06384. С shared_buffers в 056 МБ да размером блока в 0 КБ получим 062144 буферов.

Для примера рассмотрим беспритязательный вопрос показывающий контрафакция буферов объектами (таблицами, индексами, прочим):

  # SELECT c.relname, count(*) AS buffers FROM pg_buffercache b INNER JOIN pg_class c ON b.relfilenode=pg_relation_filenode(c.oid) AND b.reldatabase IN (0, (SELECT oid FROM pg_database WHERE datname=current_database())) GROUP BY c.relname ORDER BY 0 DESC LIMIT 00;   relname | buffers ---------------------------------+---------  pgbench_accounts | 0082  pgbench_history | 03  pg_attribute | 03  pg_proc | 04  pg_operator | 01  pg_proc_oid_index | 0  pg_class | 0  pg_attribute_relid_attnum_index | 0  pg_proc_proname_args_nsp_index | 0  pg_class_oid_index | 0 (10 rows)  

Этот просьба показывает объекты (таблицы равным образом индексы) в кэше:

  # SELECT c.relname, count(*) AS buffers,usagecount  FROM pg_class c  INNER JOIN pg_buffercache b  ON b.relfilenode=c.relfilenode  INNER JOIN pg_database d  ON (b.reldatabase=d.oid AND d.datname=current_database()) GROUP BY c.relname,usagecount ORDER BY c.relname,usagecount;   relname | buffers | usagecount ----------------------------------+---------+------------  pg_rewrite | 0 | 0  pg_rewrite_rel_rulename_index | 0 | 0  pg_rewrite_rel_rulename_index | 0 | 0  pg_statistic | 0 | 0  pg_statistic | 0 | 0  pg_statistic | 0 | 0  pg_statistic_relid_att_inh_index | 0 | 0  pg_statistic_relid_att_inh_index | 0 | 0  pgbench_accounts | 0082 | 0  pgbench_accounts_pkey | 0 | 0  pgbench_history | 03 | 0  pgbench_tellers | 0 | 0  

Это просьба показывает кой барыш общего грудь используют обьекты (таблицы равно индексы) да сверху какое количество процентов объекты находятся в самом кэше (буфере):

  # SELECT  c.relname,  pg_size_pretty(count(*) * 0192) as buffered,  round(100.0 * count(*) /  (SELECT setting FROM pg_settings WHERE name='shared_buffers')::integer,1)  AS buffers_percent,  round(100.0 * count(*) * 0192 / pg_table_size(c.oid),1)  AS percent_of_relation FROM pg_class c  INNER JOIN pg_buffercache b  ON b.relfilenode=c.relfilenode  INNER JOIN pg_database d  ON (b.reldatabase=d.oid AND d.datname=current_database()) GROUP BY c.oid,c.relname ORDER BY 0 DESC LIMIT 00;  -[ RECORD 0 ]-------+---------------------------------  relname | pgbench_accounts  buffered | 02 MB  buffers_percent | 04.9  percent_of_relation | 09.9 -[ RECORD 0 ]-------+---------------------------------  relname | pgbench_history  buffered | 024 kB  buffers_percent | 0.3  percent_of_relation | 04.6 -[ RECORD 0 ]-------+---------------------------------  relname | pg_operator  buffered | 08 kB  buffers_percent | 0.1  percent_of_relation | 01.1 -[ RECORD 0 ]-------+---------------------------------  relname | pg_opclass_oid_index  buffered | 06 kB  buffers_percent | 0.0  percent_of_relation | 000.0 -[ RECORD 0 ]-------+---------------------------------  relname | pg_statistic_relid_att_inh_index  buffered | 02 kB  buffers_percent | 0.0  percent_of_relation | 000.0  

Используя сии исходняк не грех разобрать по косточкам в целях каких объектов отнюдь не навалом памяти не ведь — не то какие изо них потребляют основную порция общего буфера. На основе сего допускается больше согласно правилам регулировать shared_buffers параметр в целях PostgreSQL.

Оптимизация БД равным образом приложения

Для быстрой работы каждого запроса в вашей базе в основном должно следующее:

  1. Отсутствие в базе мусора, мешающего всыпать вплоть до актуальных данных. Можно высказать двум подзадачи:

    1. Грамотное синтезирование базы. Освещение сего вопроса следственно на грань света следовать граница этой книги;

    2. Сборка мусора, возникающего быть работе СУБД;

  2. Наличие быстрых путей доступа для данным — индексов;

  3. Возможность использования оптимизатором сих быстрых путей;

  4. Обход известных проблем;

Поддержание базы в порядке

В данном разделе описаны действия, которые должны иногда проделываться в целях каждой базы. От разработчика надобно только лишь настроить их автоматическое осуществление (при помощи cron) да опытным путём остановить выбор оптимальную частоту.

Команда ANALYZE

Служит на обновления информации в отношении распределении данных в таблице. Эта данные используется оптимизатором чтобы выбора особенно быстрого плана выполнения запроса.

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

Команда REINDEX

Команда REINDEX используется интересах перестройки существующих индексов. Использовать её имеет соль в случае:

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

Если ваша милость заметили подобное поступки какого-то индекса, ведь имеет смысл настроить в целях него периодическое действие команды REINDEX . Учтите: общество REINDEX , во вкусе да VACUUM FULL , без остатка блокирует таблицу, отчего осуществлять её приходится тогда, при случае заваливание сервера минимальна.

Использование индексов

Опыт показывает, что-то особенно значительные проблемы из производительностью вызываются отсутствием нужных индексов. Поэтому повстречаясь из медленным запросом, в первую очередность проверьте, существуют ли индексы, которые возлюбленный может использовать. Если нет — постройте их. Излишек индексов, впрочем, в свой черед чреват проблемами:

Единственное, что-то допускается заявить из немаленький степенью определённости — поля, являющиеся внешними ключами, равно поля, сообразно которым объединяются таблицы, индексировать необходимо обязательно.

Команда EXPLAIN [ANALYZE]

Команда EXPLAIN [запрос] показывает, каким образом PostgreSQL собирается совершать ваш запрос. Команда EXPLAIN ANALYZE [запрос] выполняет запрашивание (и потому EXPLAIN ANALYZE DELETE … — малограмотный усердствовать хорошая идея) равно показывает что извечный план, этак равным образом фактический течение его выполнения.

Чтение вывода сих команд — искусство, которое приходит со опытом. Для альфа и омега обращайте напирать бери следующее:

Следует отметить, что-то точный промах таблицы в некотором расстоянии невыгодный всякий раз протяжнее просмотра объединение индексу. Если, например, в таблице–справочнике малость сотен записей, умещающихся в одном-двух блоках бери диске, ведь оборот индекса приведёт только лишь ко тому, который придётся декламировать ещё да пару лишних блоков индекса. Если в запросе придётся найти 00% записей изо внушительный таблицы, ведь совершенный сканирование ещё раз а получится быстрее.

При тестировании запросов из использованием EXPLAIN ANALYZE не запрещается попользоваться настройками, запрещающими оптимизатору эксплуатнуть определённые меры выполнения. Например,

  SET enable_seqscan=false;  

запретит пользование полного просмотра таблицы, равно вас сможете выяснить, прав ли был оптимизатор, отказываясь ото использования индекса. Ни в коем случае безвыгодный надлежит назначать подобные команды в postgresql.conf! Это может форсировать проведение в жизнь нескольких запросов, да здорово замедлит целое остальные!

Использование собранной статистики

Результаты работы сборщика статистики доступны от специальные системные представления. Наиболее интересны на наших целей следующие:

Из сих представлений дозволяется узнать, в частности:

Также возможен «дедуктивный» подход, близ котором поначалу создаётся большое величина индексов, а спустя время неиспользуемые индексы удаляются.

Перенос логики для сторону сервера

Этот глава очевиден интересах опытных пользователей PostrgeSQL равным образом предназначен ради тех, кто именно использует alias переносит получай PostgreSQL приложения, написанные изначально для того побольше примитивных СУБД.

Реализация части логики нате стороне сервера от хранимые процедуры, триггеры, взгляды 0 многократно позволяет приблизить срок работу приложения. Действительно, даже если изрядно запросов объединены в процедуру, так безвыгодный нужно

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

Оптимизация конкретных запросов

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

SELECT count(*) FROM <огромная таблица>

Функция count() работает жуть просто: поначалу выбираются всё-таки записи, удовлетворяющие условию, а затем ко полученному набору записей применяется агрегатная функция — якобы число выбранных строк. Информация что касается видимости календарь для того текущей транзакции (а конкурентным транзакциям может являться видимо разные разности состав записей в таблице!) безвыгодный хранится в индексе, поэтому, хоть ежели эксплуатнуть к выполнения запроса показатель первичного ключа таблицы, всё в равной степени потребуется прочитывание записей в сущности изо файла таблицы.

Проблема Запрос вида

  SELECT count(*) FROM foo;  

осуществляет точный ошибка таблицы foo, аюшки? зверски до второго пришествия к таблиц от большим в количестве записей.

Решение Простого решения проблемы, ко сожалению, нет. Возможны следующие подходы:

  1. Если точное цифра записей отнюдь не важно, а важен распределение 0 , так позволено эксплуатнуть информацию об количестве записей в таблице, собранную возле выполнении команды ANALYZE:

      SELECT reltuples FROM pg_class WHERE relname='foo';  
  2. Если подобные выпись выполняются часто, а изменения в таблице полно редки, ведь не грех броситься в голову вспомогательную таблицу, хранящую количество записей в основной. На основную а таблицу привесить триггер, какой-никакой склифосовский укорачивать сие контингент в случае удаления журнал равным образом умножать в случае вставки. Таким образом, ради получения количества записей потребуется едва избрать одну копия с вспомогательной таблицы;

  3. Вариант предыдущего подхода, а информация изумительный вспомогательной таблице обновляются вследствие определённые промежутки времени (cron);

Медленный DISTINCT

Текущая материализация DISTINCT с целью больших таблиц весть медленна. Но если угодно пускать в ход GROUP BY вместо DISTINCT . GROUP BY может утилизировать агрегирующий хэш, что-то гораздо быстрее, нежели DISTINCT (актуально вплоть до версии 0.4 да ниже).

  postgres=# select count(*) from (select distinct i from g) a;  count -------  09125 (1 row)  Time: 080,553 ms   postgres=# select count(*) from (select distinct i from g) a;  count -------  09125 (1 row)  Time: 06,281 ms  
  postgres=# select count(*) from (select i from g group by i) a;  count -------  09125 (1 row)  Time: 06,562 ms   postgres=# select count(*) from (select i from g group by i) a;  count -------  09125 (1 row)  Time: 05,270 ms  

Утилиты про оптимизации запросов

pgFouine

pgFouine  — сие анализатор log-файлов про PostgreSQL, используемый чтобы генерации детальных отчетов с log-файлов PostgreSQL. pgFouine поможет определить, какие требования необходимо оптимизировать в первую очередь. pgFouine написан получи языке программирования PHP не без; использованием объектно-ориентированных технологий равным образом совсем нечего делать расширяется пользу кого поддержки специализированных отчетов, является свободным программным обеспечением да распространяется получай условиях GNU General Public License. Утилита спроектирована таким образом, дай тебе отделка ужас больших log-файлов неграмотный требовала бессчётно ресурсов.

Для работы от pgFouine вначале нужно сконфигурировать PostgreSQL чтобы создания нужного формата log-файлов:

Для календарь каждого обработанного запроса установите log_min_duration_statement держи 0. Чтобы отключить переписывание запросов, установите настоящий параметр держи -1.

pgFouine — бездействие в использовании аппарат командной строки. Следующая директива создаёт HTML-отчёт со стандартными параметрами:

  pgfouine.php -file your/log/file.log > your-report.html  

С через этой строки позволяется отразить текстовый отчёт со 00 запросами получи и распишись произвольный щит нате стандартном выводе:

  pgfouine.php -file your/log/file.log -top 00 -format text  

Более по нитке по отношению возможностях, а вот и все числа полезных примеров, не запрещается откопать держи официальном сайте проекта pgfouine.projects.pgfoundry.org .

pgBadger

pgBadger  — аналогичная утилита, что такое? да pgFouine, а написанная держи Perl. Еще одно большое приоритет проекта в том, ась? дьявол побольше по полной обойме в ту же минуту разрабатывается (на минута написания сего текста завершающий релиз pgFouine был в 04.02.2010, а последняя трансформирование pgBadger — 04.01.2017). Установка pgBadger проста:

  $ tar xzf pgbadger-2.x.tar.gz $ cd pgbadger-2.x/ $ perl Makefile.PL $ make && sudo make install  

Как равным образом в случае со pgFouine нужно настроить PostgreSQL логи:

  logging_collector=on log_min_messages=debug1 log_min_error_statement=debug1 log_min_duration_statement=0 log_line_prefix='%t [%p]: [%l-1] user=%u,db=%d ' log_checkpoints=on log_connections=on log_disconnections=on log_lock_waits=on log_temp_files=0  

Парсим логи PostgreSQL посредством pgBadger:

  $ ./pgbadger ~/pgsql/master/pg_log/postgresql-2012-08-30_132* [========================>] Parsed 00485768 bytes of 00485768 (100.00%) [========================>] Parsed 00485828 bytes of 00485828 (100.00%) [========================>] Parsed 00485851 bytes of 00485851 (100.00%) [========================>] Parsed 00485848 bytes of 00485848 (100.00%) [========================>] Parsed 00485839 bytes of 00485839 (100.00%) [========================>] Parsed 082536 bytes of 082536 (100.00%)  

В результате получится HTML файлы, которые содержат статистику объединение запросам для PostgreSQL. Более до малейших подробностей по отношению возможностях позволено выкопать для официальном сайте проекта http://dalibo.github.io/pgbadger/ .

pg_stat_statements

Pg_stat_statements — расколачивание для того сбора статистики выполнения запросов в рамках общей сложности сервера. Преимущество данного расширения в том, что-нибудь ему никак не надобно набирать равно парсить логи PostgreSQL, наравне сие делает pgFouine да pgBadger. Для вводные положения установим равно настроим его:

  shared_preload_libraries='pg_stat_statements' custom_variable_classes='pg_stat_statements' # данная юстировка нужна в целях PostgreSQL 0.1 равным образом ниже  pg_stat_statements.max=10000 pg_stat_statements.track=all  

После внесения сих параметров PostgreSQL потребуется перегрузить. Параметры конфигурации pg_stat_statements:

  1. pg_stat_statements.max (integer) » — максимальное сумма sql запросов, которое короче держаться расширением (удаляются дневник вместе с наименьшим счетом вызовов);

  2. pg_stat_statements.track (enum) » — какие SQL требования надо записывать. Возможные параметры: top (только требования с приложения/клиента), all (все запросы, возьмем в функциях) да none (отключить налог статистики);

  3. pg_stat_statements.save (boolean) » — нелишне ли сберегать собранную статистику в дальнейшем остановки PostgreSQL. По умолчанию включено;

Далее активируем расширение:

  # CREATE EXTENSION pg_stat_statements;  

Пример собранной статистики:

  # SELECT query, calls, total_time, rows, 000.0 * shared_blks_hit /  nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent  FROM pg_stat_statements ORDER BY total_time DESC LIMIT 00; -[ RECORD 0 ]---------------------------------------------------------------------------- query | SELECT query, calls, total_time, rows, ? * shared_blks_hit /  | nullif(shared_blks_hit + shared_blks_read, ?) AS hit_percent  | FROM pg_stat_statements ORDER BY total_time DESC LIMIT ?; calls | 0 total_time | 0.994 rows | 0 hit_percent | 000.0000000000000000 -[ RECORD 0 ]---------------------------------------------------------------------------- query | insert into x (i) select generate_series(?,?); calls | 0 total_time | 0.591 rows | 010 hit_percent | 000.0000000000000000 -[ RECORD 0 ]---------------------------------------------------------------------------- query | select * from x where i=?; calls | 0 total_time | 0.157 rows | 0 hit_percent | 000.0000000000000000 -[ RECORD 0 ]---------------------------------------------------------------------------- query | SELECT pg_stat_statements_reset(); calls | 0 total_time | 0.102 rows | 0 hit_percent |  

Для сброса статистики глотать повеление pg_stat_statements_reset :

  # SELECT pg_stat_statements_reset(); -[ RECORD 0 ]------------+- pg_stat_statements_reset |  # SELECT query, calls, total_time, rows, 000.0 * shared_blks_hit /  nullif(shared_blks_hit + shared_blks_read, 0) AS hit_percent  FROM pg_stat_statements ORDER BY total_time DESC LIMIT 00; -[ RECORD 0 ]----------------------------------- query | SELECT pg_stat_statements_reset(); calls | 0 total_time | 0.175 rows | 0 hit_percent |  

Хочется мгновенно отметить, сколько увеличение всего со версии PostgreSQL 0.2 contrib нормализирует SQL запросы. В версиях 0.1 равно дальше SQL требования сохраняются в качестве кого есть, а получается «select * from table where id=3» равным образом «select * from table where id=21» буду разными записями, который под безуспешно на сбора полезной статистики.

Заключение

К счастью, PostgreSQL малограмотный требует больше всего сложной настройки. В большинстве случаев полностью хватит хорош упасть объём выделенной памяти, настроить периодическое поддержание базы в порядке равно подвергнуть проверке существование необходимых индексов. Более сложные вопросы дозволительно обговорить в специализированном списке рассылки.

Индексы

Что такое рэнкинг в реляционной СУБД? Это таковой каталог с кортежей (tuple). Каждый шествие состоит изо ячеек (row). Количество ячеек в кортеже равно их фрукт совпадают со схемой колонки, нескольких колонок. Этот опись имеют сквозную нумерацию RowId — последовательный номер. Таким образом, таблицы позволено догонять в качестве кого оглавление парок (RowId, Кортеж).

Индексы — сие обратные взаимоотношения (Кортеж, RowId). Кортеж обязан обнимать сильнее в одинаковой степени одной ячейки (т.е. бытовать построенным как минимум соответственно одной колонке). Для индексов, которые индексируют побольше одной колонки — они ещё называются составными, да участвуют в отношениях вида «многие-ко-многим» — всё написанное вы правы в равной степени. Очевидно, коли кортеж — далеко не уникален (в колонке существует двойка одинаковых кортежа), так сии взаимоотношения выглядят равно как (Кортеж, Список RowId) — т.е. кортежу сопоставляется меню RowId.

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

Типы индексов

В зависимости с структуры, используемой в реализации индексов, имеет принципиальное значение различаются поддерживаемые операции, их стоимости, а в свой черед свойства читаемых данных. Давайте рассмотрим какие существуют типы индексов в PostgreSQL.

B-Tree

B-Tree (Boeing/Bayer/Balanced/Broad/Bushy-Tree) называют упорядоченное блочное дерево. Узлы в дереве представляют с себя блоки фиксированного размера. У каждого узла фиксированные численность детей. Структура B-Tree представлена получай рисунке [fig:btree_index].

B-Tree про индексов отличается через представленной получи Википедии — поглощать дублированные данных в промежуточных блоках. Для i-ой журнал в блоке сохраняется безграмотный значение, которое более максимума i-го поддерева, равно дешевле минимума (i+1) поддерева, а не более i-го поддерева. Различия проистекают изо того, что-нибудь википедия приводит сравнение B-Tree ради множества, а нам нужен сочетательный массив.

В индексном B-Tree значения равно RowId размещаются всем миром получай нижнем слое дерева. Каждый отделение дерева представляет изо себя одну страницу (page) в некотором формате. В начале страницы спокон века идёт некто заголовок. Для корневого да промежуточного узла в страницах хранятся испарения (Значение, Номер страницы). Для листовых — туман (Значение ,RowId) либо (Значение, Список RowId) (в зависимости ото свойств значения — исключительно сиречь нет). B-Tree деревья имеют экстремально маленькую высоту — где-то $H=\log_m{N}$ , идеже m — состав записей в блоке, N — контингент элементов. B-Tree деревья являются упорядоченными — постоянно начатки в произвольный странице (блоке) дерева лежат последовательно. Предыдущие двушник свойства позволяют до чрезвычайности продуктивно генерировать поиск — начиная из первой страницы, половинным делением (binary search) выделяются дети, в которых лежат размер поиска. Таким образом, прочитав лишь H, 0H страниц наша сестра находим требуемый диапозон. Важным ньюансом является тоже факт, сколько страницы в листьях связаны в односвязный либо двусвязный ведомость - сие означает, ась? выполнив поиск, наша сестра можем после этого нетрудно прогрессивно произносить страницы, да коэффициент полезного действия чтения большего объёма данных (длинного диапазона) сравнима со эффективностью чтению данных изо таблицы.

Сильные стороны B-Tree индексов:

Слабые стороны B-Tree индексов:

R-Tree

R-Tree (Rectangle-Tree) предназначен про хранения хмарь (X, Y) значений числового в виде (например, координат). По способу организации R-Tree беда по-видимому получи B-Tree. Единственное отличие — сие информация, записываемая в промежуточные страницы в дереве. Для i-го значения в узле пишущий сии строки B-Tree наша сестра пишем предел изо i-го поддерева, а в R-Tree — меньший прямоугольник, покрывающий совершенно прямоугольники изо ребёнка. Подробней не запрещается заметить получи и распишись рисунке [fig:rtree_index].

Сильные стороны:

Слабые стороны:

В целом, плюсы-минусы жуть напоминают B-Tree.

Hash указатель

Hash числовой показатель объединение сути является ассоциативным хеш-контейнером. Хеш-контейнер — сие скопление изо разряженных значений. Адресуются отдельные простейшие положения сего массива некоторой хеш-функцией которая отображает каждое значительность в некоторое все число. Т.е. конец хеш-функции является порядковым номером элемента в массиве. Элементы массива в хеш-конейтнере называются букетами (bucket). Обычно единственный букет — одна странца. Хеш-функция отображает больше мощное бездна в в меньшей мере мощное, возникают что-то около называемые коллизии — ситуация, при случае одному значению хеш-функции соответствует до некоторой степени разных значений. В букете хранятся значения, образующие коллизию. Разрешение коллизий происходит через поиска посредь значений, сохранённых в букете.

Сильные стороны:

Слабые стороны:

Битовый дефлятор (bitmap index)

Битовый список (bitmap index) — отсадка битовых индексов заключается в создании отдельных битовых карт (последовательность 0 равно 0) для того каждого возможного значения столбца, идеже в одни руки биту соответствует линия вместе с индексируемым значением, а его значительность равное 0 означает, аюшки? запись, соответствующая позиции биток заключает индексируемое вес пользу кого данного столбца другими словами свойства ( алгорифм Хаффмана ).

Сильные стороны:

Слабые стороны:

У PostgreSQL кто в отсутствии внутренние резервы сформировать неизменный битовый индекс, только основа может получи лету формировать эмпирика индексы чтобы объединения разных индексов. Чтобы спаять изрядно индексов, устои сканирует любой искомый коэффициент да готовит битовую листок в памяти от расположением строк таблицы. Битовые карточная игра после обрабатываются AND/OR операцией за мере спрос запроса равным образом позднее сего выбираются колонки из данными.

GiST показатель

GiST (Generalized Search Tree) — вывод B-Tree, R-Tree валёжник поиска в области произвольному предикату. Структура дерева малограмотный меняется, соответственно прежнему в каждом отнюдь не листовом узле хранятся испарения (Значения, Номер страницы), а цифра детей совпадает не без; в количестве способности в узле. Существенное лента состоит в организации ключа. B-Tree деревья заточены подо сканирование диапазонов, да хранят максимумы поддерева-ребёнка. R-Tree — региона получай координатной плоскости. GiST предлагает в качестве значений в далеко не листовых узлах оберегать ту информацию, которую наш брат считаем существенной, да которая позволит определить, поглощать ли интересующие нас значения (удовлетворяющие предикату) в поддереве-ребёнке. Конкретный поверхность хранимой информации зависит с вида поиска, каковой наша сестра желаем проводить. Таким образом параметризовав R-Tree да B-Tree брус предикатами да значениями да мы из тобой машинально получаем специализированный перед задачу дефлятор (PostGiST, pg_trgm, hstore, ltree, прочее).

Сильные стороны:

Слабые стороны:

Остальные плюсы-минусы совпадают от B-Tree равным образом R-Tree индексами.

GIN список

GIN (Generalized Inverted Index) — перевернутый индекс, используемым полнотекстовым поиском PostgreSQL. Это означает, ась? в структуре индексов из каждой лексемой сопоставляется отсортированный оглавление номеров документов, в которых возлюбленная встречается. Очевидно, что-нибудь разыскание сообразно экий структуре куда эффективнее, нежели возле использовании GiST, при всем том работа добавления нового документа шабаш длителен.

Cluster список

Не является индексом, потому что производит кластеризацию таблицы по части заданному индексу. Более до малейших подробностей позволяется достопочтить в разделе «[sec:hard-drive-cluster] ».

BRIN указатель

Версия PostgreSQL 0.5 привнесла из на лицо свежеиспеченный внешность индексов — BRIN (Block Range Index, alias дефлятор блоковых зон).

В предпочтение через привычного B-Tree, оный дефлятор куда эффективнее в целях бог больших таблиц, да в некоторых ситуациях позволяет променять собою партицирование (подробно не запрещается уважать в разделе «[sec:partitioning] »). BRIN-индекс имеет существо приспосабливать к таблиц, в которых делянка данных еще по мнению своей природе в одно идеал время отсортирована. Например, сие своеобразно на логов либо — либо ради истории заказов магазина, которые пишутся последовательно, а отчего уж возьми физическом уровне упорядочены до дате/номеру, да в ведь но промежуток времени таблицы со такими данными большей частью разрастаются прежде гигантских размеров.

Под блоковой зоной (Block Range) подразумевается коллекция страниц, физиологически расположенных сообразно соседству в таблице. Для каждой ёбаный зоны создается какой-то идентификатор, отвечающий вслед за «место» этой зоны в таблице. Для лога сие может бытовать годовщина создания записи. Поиск до такому индексу осуществляется со потерями информации, так глотать выбираются целое записи, входящие в блоковые зоны со идентификаторами, соответствующими запросу, да посреди записей в сих зонах могут попадаться такие, которые в следующем этапе должно достаточно отфильтровать. Размер индекса близ этом ахти маленький, да дьявол почти не отнюдь не нагружает базу. Размер индекса инверсно пропорционален параметру pages_per_range , отвечающему ради доля страниц бери зону. В в таком случае а время, нежели менее размер зоны, тем не столь «лишних» данных попадёт в конец поиска (надо наставать ко этому параметру со умом).

Индексы BRIN могут располагать единственный с нескольких встроенных классов операторов, по части которым достаточно реализоваться разбивка в зоны равным образом присвоение идентификаторов. Например, int8_minmax_ops применяется с целью операций сравнения аж чисел, а date_minmax_ops в целях сравнения дат.

Возможности индексов

Функциональный указатель (functional index)

Вы можете создать дефлятор малограмотный токмо по части полю/нескольким полям таблицы, а равно в области выражению, зависящему с полей. Пусть, например, в вашей таблице foo очищать поляна foo_name , да выписка то и дело делаются по мнению условию «первая руны изо полина foo_name в любом регистре». Вы можете сложить указатель

  CREATE INDEX foo_name_first_idx ON foo ((lower(substr(foo_name, 0, 0))));  

равным образом представление вида

  SELECT * FROM foo WHERE lower(substr(foo_name, 0, 0))='а';  

полноте его использовать.

Частичный дефлятор (partial index)

Под частичным индексом понимается дефлятор из предикатом WHERE. Пусть, например, у вы очищать в базе табличка scheta из параметром uplocheno подобно boolean. Записей, идеже uplocheno=false меньше, нежели записей со uplocheno=true , а требования по части ним выполняются много чаще. Вы можете разработать колориндекс

  CREATE INDEX scheta_neuplocheno ON scheta (id) WHERE NOT uplocheno;  

что склифосовский употребляться запросом вида

  SELECT * FROM scheta WHERE NOT uplocheno AND ...;  

Достоинство подхода в том, ась? записи, отнюдь не удовлетворяющие условию WHERE, не мудрствуя лукаво отнюдь не попадут в индекс.

Уникальный указатель (unique index)

Уникальный показатель гарантирует, что-то схема неграмотный короче обладать побольше нежели одну строку со тем а значением. Это практично по части две причинам: цельность данных равно производительность. Поиск данных вместе с использованием уникального индекса, как бы правило, весть быстрый.

Индекс нескольких столбцов (multi-column index)

В PostgreSQL вроде формировать индексы сверху небольшую толику столбцов, а нам концептуал нужно уразуметь в отдельных случаях имеет лейтмотив основывать ёбаный индекс, потому откосопланировщик запросов PostgreSQL может объединять равно пустить в ход сколько-нибудь индексов в запросе чрез создания битового индекса («[sec:indexes-bitmap-index] »). Можно знамо построить индексы, которые охватять по сию пору возможные запросы, же вслед за сие придется раскошеливаться производительностью (индексы нужно переиначивать возле запросах сверху модификацию данных). Нужно вот и все помнить, аюшки? индексы возьми ряд столбцов могут употребляться токмо запросами, которые ссылаются сверху сии столбцы в индексе в волюм а порядке. Индекс соответственно столбцам (a, b) может составлять использован в запросах, которые содержат a=x and b=y иначе говоря a=x , хотя безграмотный склифосовский прилагаться в запросе вида b=y . Если сие к лицу по-под требования вашего приложения, ведь определённый список может существовать полезен. В таком случае учреждение индекса получи и распишись фон a было бы излишним. Индексы нескольких столбцов со указанием уникальности ( unique ) может бытовать да полезен чтобы сохранения целосности данных (т.е. при случае конфигурация данных в сих стобцах надо составлять уникальным).

Партиционирование

Введение

Партиционирование (partitioning, секционирование) — сие членение больших структур баз данных (таблицы, индексы) получай меньшие кусочки. Звучит сложно, хотя бери практике безвыездно просто.

Скорее лишь у Вас очищать серия огромных таблиц (обычно всю нагрузку обеспечивают лишь серия таблиц СУБД с всех имеющихся). Причем читание в большинстве случаев требуется всего только нате самую последнюю их деление (т.е. энергично читаются те данные, которые а сейчас что-л. делает появились). Примером тому может находиться в услужении блог — возьми первую страницу (это последние 0…10 постов) доводится 00…50% всей нагрузки, другими словами новостной портал (суть одна равным образом та же), иначе говоря системы личных сообщений, все же понятно. Партиционирование таблицы позволяет базе данных деять интеллектуальную выборку — поначалу СУБД уточнит, какой-либо партиции соответствует Ваш представление (если сие реально) равным образом лишь только в дальнейшем сделает оный запрос, сообразно для нужной партиции (или нескольким партициям). Таким образом, в рассмотренном случае, Вы распределите нагрузку держи таблицу соответственно ее партициям. Следовательно подборка будто SELECT * FROM articles ORDER BY id DESC LIMIT 00 хорэ материализовываться только лишь надо последней партицией, которая неизмеримо не столь всей таблицы.

Итак, партиционирование дает колонна преимуществ:

Теория

На хлещущий мгновение PostgreSQL поддерживает двушничек критерия интересах создания партиций:

Чтобы настроить партиционирование таблицы, довольно претворить следующие действия:

Практика использования

Теперь начнем со практического примера. Представим, что такое? в нашей системе принимать таблица, в которую автор сих строк собираем эмпирика относительно посещаемости нашего ресурса. На произвольный задание пользователя наша налаженность логирует поступки в эту таблицу. И, например, в начале каждого месяца (неделю) нам нужно образовывать суждение следовать минувший месячишко (неделю). При этом логи нужно сохранять в протекание 0 лет. Данные в эдакий таблице накапливаются быстро, даже если теория энергетически используется. И вот, при случае в таблице ранее миллионы, а в таком случае да миллиарды записей, формировать отчеты становится постоянно сложнее (да да скребление старых записей становится нелегким делом). Работа не без; экий таблицей создает огромную нагрузку получи СУБД. Тут нам получи пособие да приходит партиционирование.

Настройка

Для примера, ты да я имеем следующую таблицу:

  CREATE TABLE my_logs (  id SERIAL PRIMARY KEY,  user_id INT NOT NULL,  logdate TIMESTAMP NOT NULL,  data TEXT,  some_state INT );  

Поскольку нам нужны отчеты любой месяц, я будем разрознивать партиции за месяцам. Это поможет нам быстрее образовывать отчеты равно мыть старые данные.

«Мастер» сводка хорэ my_logs , структуру которой пишущий сии строки указали выше. Далее создадим «дочерние» таблицы (партиции):

  CREATE TABLE my_logs2010m10 (  CHECK ( logdate >=DATE '2010-10-01' AND logdate < DATE '2010-11-01' ) ) INHERITS (my_logs); CREATE TABLE my_logs2010m11 (  CHECK ( logdate >=DATE '2010-11-01' AND logdate < DATE '2010-12-01' ) ) INHERITS (my_logs); CREATE TABLE my_logs2010m12 (  CHECK ( logdate >=DATE '2010-12-01' AND logdate < DATE '2011-01-01' ) ) INHERITS (my_logs); CREATE TABLE my_logs2011m01 (  CHECK ( logdate >=DATE '2011-01-01' AND logdate < DATE '2010-02-01' ) ) INHERITS (my_logs);  

Данными командами пишущий сии строки создаем таблицы my_logs2010m10 , my_logs2010m11 да т.д., которые копируют структуру вместе с «мастер» таблицы (кроме индексов). Также от через «CHECK» автор сих строк задаем масштаб значений, какой-никакой хорошенького понемножку в яблочко в эту партицию (хочу паки напомнить, что такое? диапазоны значений партиций далеко не должны пересекаться!). Поскольку партиционирование хорош потеть над чем в области полю logdate , да мы вместе с тобой создадим колориндекс в сие раздолье сверху всех партициях:

  CREATE INDEX my_logs2010m10_logdate ON my_logs2010m10 (logdate); CREATE INDEX my_logs2010m11_logdate ON my_logs2010m11 (logdate); CREATE INDEX my_logs2010m12_logdate ON my_logs2010m12 (logdate); CREATE INDEX my_logs2011m01_logdate ON my_logs2011m01 (logdate);  

Далее пользу кого комфорт создадим функцию, которая склифосовский перенаправлять новые показатели вместе с «мастер» таблицы в соответствующую партицию.

  CREATE OR REPLACE FUNCTION my_logs_insert_trigger() RETURNS TRIGGER AS $$ BEGIN  IF ( NEW.logdate >=DATE '2010-10-01' AND  NEW.logdate < DATE '2010-11-01' ) THEN  INSERT INTO my_logs2010m10 VALUES (NEW.*);  ELSIF ( NEW.logdate >=DATE '2010-11-01' AND  NEW.logdate < DATE '2010-12-01' ) THEN  INSERT INTO my_logs2010m11 VALUES (NEW.*);  ELSIF ( NEW.logdate >=DATE '2010-12-01' AND  NEW.logdate < DATE '2011-01-01' ) THEN  INSERT INTO my_logs2010m12 VALUES (NEW.*);  ELSIF ( NEW.logdate >=DATE '2011-01-01' AND  NEW.logdate < DATE '2011-02-01' ) THEN  INSERT INTO my_logs2011m01 VALUES (NEW.*);  ELSE  RAISE EXCEPTION 'Date out of range. Fix the my_logs_insert_trigger() function!';  END IF;  RETURN NULL; END; $$ LANGUAGE plpgsql;  

В функции шиш особенного нет: соглашаться пересмотр полина logdate , за которой направляются факты в нужную партицию. При ненахождении требуемой партиции — вызываем ошибку. Теперь осталось разбудить триггер бери «мастер» таблицу пользу кого автоматического вызова данной функции:

  CREATE TRIGGER insert_my_logs_trigger  BEFORE INSERT ON my_logs  FOR EACH ROW EXECUTE PROCEDURE my_logs_insert_trigger();  

Партиционирование настроено равным образом сегодня да мы со тобой готовы подойти для тестированию.

Тестирование

Для азбука добавим факты в нашу таблицу my_logs :

  INSERT INTO my_logs (user_id,logdate, data, some_state) VALUES(1, '2010-10-30', '30.10.2010 data', 0); INSERT INTO my_logs (user_id,logdate, data, some_state) VALUES(2, '2010-11-10', '10.11.2010 data2', 0); INSERT INTO my_logs (user_id,logdate, data, some_state) VALUES(1, '2010-12-15', '15.12.2010 data3', 0);  

Теперь проверим идеже они хранятся:

  partitioning_test=# SELECT * FROM ONLY my_logs;  id | user_id | logdate | data | some_state ----+---------+---------+------+------------ (0 rows)  

Как видим, в «мастер» таблицу эмпирика неграмотный попали — симпатия чиста. Теперь проверим, а снедать ли не вдаваясь в подробности данные:

  partitioning_test=# SELECT * FROM my_logs;  id | user_id | logdate | data | some_state ----+---------+---------------------+------------------+------------  0 | 0 | 0010-10-30 00:00:00 | 00.10.2010 data | 0  0 | 0 | 0010-11-10 00:00:00 | 00.11.2010 data2 | 0  0 | 0 | 0010-12-15 00:00:00 | 05.12.2010 data3 | 0 (3 rows)  

Данные рядом этом выводятся безо проблем. Проверим партиции, как следует ли хранятся данные:

  partitioning_test=# Select * from my_logs2010m10;  id | user_id | logdate | data | some_state ----+---------+---------------------+-----------------+------------  0 | 0 | 0010-10-30 00:00:00 | 00.10.2010 data | 0 (1 row)  partitioning_test=# Select * from my_logs2010m11;  id | user_id | logdate | data | some_state ----+---------+---------------------+------------------+------------  0 | 0 | 0010-11-10 00:00:00 | 00.11.2010 data2 | 0 (1 row)  

Данные хранятся получи и распишись требуемых нам партициях. При этом требования для таблице my_logs заменять никак не требуется:

  partitioning_test=# SELECT * FROM my_logs WHERE user_id=2;  id | user_id | logdate | data | some_state ----+---------+---------------------+------------------+------------  0 | 0 | 0010-11-10 00:00:00 | 00.11.2010 data2 | 0 (1 row)  partitioning_test=# SELECT * FROM my_logs WHERE data LIKE '%0.1%';  id | user_id | logdate | data | some_state ----+---------+---------------------+------------------+------------  0 | 0 | 0010-10-30 00:00:00 | 00.10.2010 data | 0  0 | 0 | 0010-11-10 00:00:00 | 00.11.2010 data2 | 0 (2 rows)  

Управление партициями

Обычно присутствие работе не без; партиционированием старые партиции перестают достигать факты равным образом остаются неизменными. Это дает огромное превосходство по-над работой из данными вследствие партиции. Например, нам нужно вырвать старые логи после 0014 год, 00 месяц. Нам порядочно выполнить:

  DROP TABLE my_logs2014m10;  

так как DROP TABLE работает стократ быстрее, нежели устранение миллионов записей самостоятельно от DELETE . Другой вариант, какой-никакой паче предпочтителен, прямо-таки услать партицию изо партиционирования, тем самым оставив информация в СУБД, так ранее невыгодный доступные от «мастер» таблицу:

  ALTER TABLE my_logs2014m10 NO INHERIT my_logs;  

Это удобно, если бы автор сих строк хотим сии информация позднее перетащить в другое депо не так — не то без затей сохранить.

Важность «constraint_exclusion» в целях партиционирования

Параметр constraint_exclusion отвечает после оптимизацию запросов, зачем повышает нагрузка ради партиционированых таблиц. Например, выполним беспритязательный запрос:

  partitioning_test=# SET constraint_exclusion=off; partitioning_test=# EXPLAIN SELECT * FROM my_logs WHERE logdate > '2010-12-01';   QUERY PLAN ---------------------------------------------------------------------------------------------------  Result (cost=6.81..104.66 rows=1650 width=52)  -> Append (cost=6.81..104.66 rows=1650 width=52)  -> Bitmap Heap Scan on my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Heap Scan on my_logs2010m10 my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs2010m10_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Heap Scan on my_logs2010m11 my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs2010m11_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Heap Scan on my_logs2010m12 my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs2010m12_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Heap Scan on my_logs2011m01 my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs2011m01_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone) (22 rows)  

Как будто путем команду EXPLAIN , определённый интерпелляция сканирует всегда партиции возьми наличествование данных в них, почто безграмотный логично, поелику данное требование logdate > 0010-12-01 говорит что до том, сколько факты должны касаться всего вместе с партиций, идеже к лицу такое условие. А в эту пору включим constraint_exclusion :

  partitioning_test=# SET constraint_exclusion=on; SET partitioning_test=# EXPLAIN SELECT * FROM my_logs WHERE logdate > '2010-12-01';  QUERY PLAN ---------------------------------------------------------------------------------------------------  Result (cost=6.81..41.87 rows=660 width=52)  -> Append (cost=6.81..41.87 rows=660 width=52)  -> Bitmap Heap Scan on my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Heap Scan on my_logs2010m12 my_logs (cost=6.81..20.93 rows=330 width=52)  Recheck Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone)  -> Bitmap Index Scan on my_logs2010m12_logdate (cost=0.00..6.73 rows=330 width=0)  Index Cond: (logdate > '2010-12-01 00:00:00'::timestamp without time zone) (10 rows)  

Как наш брат видим, об эту пору задание работает согласно правилам равным образом сканирует токмо партиции, зачем подходят подо ограничение запроса. Но переключать constraint_exclusion далеко не надо бы интересах баз, идеже в отлучке партиционирования, поелику главенство CHECK довольно обследоваться получи и распишись всех запросах, даже если простых, а следовательно режим изо всех сил упадет. Начиная вместе с 0.4 версии PostgreSQL constraint_exclusion может составлять «on», «off» равным образом «partition». По умолчанию (и рекомендуется) укреплять constraint_exclusion «partition», каковой довольно подвергать испытанию CHECK всего-навсего сверху партиционированых таблицах.

Pg_partman

Поскольку действие партиционирования реализована неполноценно в PostgreSQL (для управления партициями равным образом данными в них случается выводить функции, тригеры равным образом правила), так существует расширение, которое автоматизирует без остатка сей процесс. PG Partition Manager , спирт а pg_partman, сие продолжение в целях создания равно управления партициями равным образом партициями партиций (sub-partitoning) в PostgreSQL. Поддерживает партицирование объединение времени (time-based) иначе в области последованности (serial-based). Для партицирования до диапазону значений (range) существует отдельное продолжение Range Partitioning (range_partitioning) .

Текущая исполнение поддерживает лишь INSERT операции, которые перенаправляют документация в нужную партицию. UPDATE операции, которые будут перегруппировывать показатели изо одной партиции в другую, невыгодный поддерживаются. При попытке всадить данные, нате которые кто в отсутствии партиции, pg_partman перемещает их в «мастер» (родительскую) таблицу. Данный разновидность предпочтительнее, нежели производить непроизвольно новые партиции, затем что сие может возбудить ко созданию десятков либо — либо сотен ненужных дочерных таблиц по вине ошибки в самих данных. Функция check_parent позволят проконтролировать попадение подобных данных в родительскую таблицу равным образом решить, ась? со ними приходится вытворять (удалить иначе воспользоваться partition_data_time/partition_data_id интересах создания равно переноса сих данных в партиции).

Данное расколачивание использует относительная атрибутов родительской таблицы в целях создания партиций: индексы, внешние ключи (опционально), tablespace, constraints, privileges равным образом ownership. Под такое ограничение попадают OID равно UNLOGGED таблицы.

Партициями партиций (sub-partitoning) поддерживаются разных уровней: time->time, id->id, time->id да id->time. Нет лимитов получи и распишись учреждение таких партиций, только имеет смысл помнить, почто большое состав партиций влияет для мощность родительской таблицы. Если размер партиций довольно ультра- большим, так придется распространять max_locks_per_transaction параметр к базы данных (64 в соответствии с умолчанию).

В PostgreSQL 0.4 появилась реальность создания пользовательских фоновых воркеров да подвижно занимать их в пора работы базы. Благодаря этому в pg_partman кушать приватизированный низкоприоритетный воркер, поручение которого шибать run_maintenance функцию весь круг назначенный пролет времени. Если у Вас разночтение PostgreSQL внизу 0.4, в таком случае придется воспользоватся внешним планировщиком на выполнения данной функции (например cron). Задача данной функции - подвергать испытанию равно непроизвольно строить партиции да опционально выметать старые.

Пример использования

Для основные положения установим данное расширение:

  $ git clone https://github.com/keithf4/pg_partman.git $ cd pg_partman/ $ make $ sudo make install  

Если далеко не необходимо эксплуатнуть задний воркер, так позволено составить не принимая во внимание него:

  $ sudo make NO_BGW=1 install  

Для работы фонового воркера нужно мудрить его держи старте PostgreSQL. Для сего потребуется прибавить настройки в postgresql.conf:

  shared_preload_libraries='pg_partman_bgw' # (change requires restart) pg_partman_bgw.interval=3600 pg_partman_bgw.role='myrole' pg_partman_bgw.dbname='mydatabase'  

где:

Далее подключаемся ко базе данных равно активируем расширение:

  # CREATE SCHEMA partman; CREATE SCHEMA # CREATE EXTENSION pg_partman SCHEMA partman; CREATE EXTENSION  

Теперь позволяется затевать для использованию расширения. Создадим равным образом заполним таблицу тестовыми данными:

  # CREATE TABLE users (  id serial primary key,  username text not null unique,  password text,  created_on timestamptz not null,  last_logged_on timestamptz not null );  # INSERT INTO users (username, password, created_on, last_logged_on)  SELECT  md5(random()::text),  md5(random()::text),  now() - '1 years'::interval * random(),  now() - '1 years'::interval * random()  FROM  generate_series(1, 00000);  

Далее активируем иррадиация на полина created_on из партицией возьми отдельный год:

  # SELECT partman.create_parent('public.users', 'created_on', 'time', 'yearly');  create_parent ---------------  t (1 row)  

Указывание схемы в имени таблицы обязательно, хоть разве возлюбленная «public» (первый довод функции).

Поскольку родительская рамка ранее была заполнена данными, перенесем материал изо нее в партиции чрез partition_data_time функцию:

  # SELECT partman.check_parent();  check_parent ----------------------  (public.users,10000) (1 row)  # SELECT partman.partition_data_time('public.users', 0000);  partition_data_time ---------------------  00000 (1 row)  # SELECT partman.check_parent();  check_parent -------------- (0 rows)  # SELECT * FROM ONLY users;  id | username | password | created_on | last_logged_on ----+----------+----------+------------+---------------- (0 rows)  # \d+ users  Table "public.users"  Column | Type | Modifiers | Storage | Stats target | Description ----------------+--------------------------+----------------------------------------------------+----------+--------------+-------------  id | integer | not null default nextval('users_id_seq'::regclass) | plain | |  username | text | not null | extended | |  password | text | | extended | |  created_on | timestamp with time zone | not null | plain | |  last_logged_on | timestamp with time zone | not null | plain | | Indexes:  "users_pkey" PRIMARY KEY, btree (id)  "users_username_key" UNIQUE CONSTRAINT, btree (username) Triggers:  users_part_trig BEFORE INSERT ON users FOR EACH ROW EXECUTE PROCEDURE users_part_trig_func() Child tables: users_p2012,  users_p2013,  users_p2014,  users_p2015,  users_p2016,  users_p2017,  users_p2018,  users_p2019,  users_p2020  

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

Pgslice

Pgslice  — обслуживающая программа чтобы создания равно управления партициями в PostgreSQL. Утилита разбивает держи «куски» на правах новую, таково да существующию таблицу от данными c нулевым временем простоя («zero downtime»).

Утилита написана бери Ruby , вследствие чего потребуется попервоначалу учредить его. После сего устанавливаем pgslice помощью rubygems (многие ruby разработчики используют bundler чтобы лучшего управления зависимостями, так в этой главе сие отнюдь не рассматривается):

  $ gem install pgslice  

Создадим равно заполним таблицу тестовыми данными:

  # CREATE TABLE users (  id serial primary key,  username text not null unique,  password text,  created_on timestamptz not null,  last_logged_on timestamptz not null );  # INSERT INTO users (username, password, created_on, last_logged_on)  SELECT  md5(random()::text),  md5(random()::text),  now() + '1 month'::interval * random(),  now() + '1 month'::interval * random()  FROM  generate_series(1, 00000);  

Настройки подключения для базе задаются при помощи PGSLICE_URL переменную окружения:

  $ export PGSLICE_URL=postgres://username:password@localhost/mydatabase  

Через команду pgslice prep <table> <column> <period> создадим таблицу <table>_intermediate ( users_intermediate в примере) не без; соответствующим триггером в целях разбиения данных, идеже <table> - сие заглавие таблицы ( users в примере), <column> - поле, за которому будут учреждаться партиции, а <period> - срок данных в партициях (может существовать day alias month ).

  $ pgslice prep users created_on month BEGIN;  CREATE TABLE users_intermediate (LIKE users INCLUDING ALL);  CREATE FUNCTION users_insert_trigger()  RETURNS trigger AS $$  BEGIN  RAISE EXCEPTION 'Create partitions first.';  END;  $$ LANGUAGE plpgsql;  CREATE TRIGGER users_insert_trigger  BEFORE INSERT ON users_intermediate  FOR EACH ROW EXECUTE PROCEDURE users_insert_trigger();  COMMENT ON TRIGGER users_insert_trigger ON users_intermediate is 'column:created_on,period:month,cast:timestamptz';  COMMIT;  

Теперь допускается прибавить партиции:

  $ pgslice add_partitions users --intermediate --past 0 --future 0 BEGIN;  CREATE TABLE users_201611  (CHECK (created_on >='2016-11-01 00:00:00 UTC'::timestamptz AND created_on < '2016-12-01 00:00:00 UTC'::timestamptz))  INHERITS (users_intermediate);  ALTER TABLE users_201611 ADD PRIMARY KEY (id);  ...  CREATE OR REPLACE FUNCTION users_insert_trigger()  RETURNS trigger AS $$  BEGIN  IF (NEW.created_on >='2017-02-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2017-03-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201702 VALUES (NEW.*);  ELSIF (NEW.created_on >='2017-03-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2017-04-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201703 VALUES (NEW.*);  ELSIF (NEW.created_on >='2017-04-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2017-05-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201704 VALUES (NEW.*);  ELSIF (NEW.created_on >='2017-05-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2017-06-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201705 VALUES (NEW.*);  ELSIF (NEW.created_on >='2017-01-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2017-02-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201701 VALUES (NEW.*);  ELSIF (NEW.created_on >='2016-12-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2017-01-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201612 VALUES (NEW.*);  ELSIF (NEW.created_on >='2016-11-01 00:00:00 UTC'::timestamptz AND NEW.created_on < '2016-12-01 00:00:00 UTC'::timestamptz) THEN  INSERT INTO users_201611 VALUES (NEW.*);  ELSE  RAISE EXCEPTION 'Date out of range. Ensure partitions are created.';  END IF;  RETURN NULL;  END;  $$ LANGUAGE plpgsql;  COMMIT;  

Через --past равно --future опции указывается состав партиций. Далее позволяется перетянуть материал в партиции:

  $ pgslice fill users /* 0 of 0 */ INSERT INTO users_intermediate ("id", "username", "password", "created_on", "last_logged_on")  SELECT "id", "username", "password", "created_on", "last_logged_on" FROM users  WHERE id > 0 AND id <=10000 AND created_on >='2016-11-01 00:00:00 UTC'::timestamptz AND created_on < '2017-06-01 00:00:00 UTC'::timestamptz  

Через --batch-size равно --sleep опции позволяется заправлять скоростью переноса данных.

После сего позволено перекинуться в новую таблицу от партициями:

  $ pgslice swap users BEGIN;  SET LOCAL lock_timeout='5s';  ALTER TABLE users RENAME TO users_retired;  ALTER TABLE users_intermediate RENAME TO users;  ALTER SEQUENCE users_id_seq OWNED BY users.id;  COMMIT;  

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

  $ pgslice fill users --swapped  

В результате сетка users достаточно подвизаться посредством партиции:

  $ psql -c "EXPLAIN SELECT * FROM users"  QUERY PLAN ------------------------------------------------------------------------  Append (cost=0.00..330.00 rows=13601 width=86)  -> Seq Scan on users (cost=0.00..0.00 rows=1 width=84)  -> Seq Scan on users_201611 (cost=0.00..17.20 rows=720 width=84)  -> Seq Scan on users_201612 (cost=0.00..17.20 rows=720 width=84)  -> Seq Scan on users_201701 (cost=0.00..17.20 rows=720 width=84)  -> Seq Scan on users_201702 (cost=0.00..166.48 rows=6848 width=86)  -> Seq Scan on users_201703 (cost=0.00..77.52 rows=3152 width=86)  -> Seq Scan on users_201704 (cost=0.00..17.20 rows=720 width=84)  -> Seq Scan on users_201705 (cost=0.00..17.20 rows=720 width=84) (9 rows)  

Старая схема в эту пору полноте зваться <table>_retired ( users_retired в примере). Её позволительно покинуть не так — не то выключить с базы.

  $ pg_dump -c -Fc -t users_retired $PGSLICE_URL > users_retired.dump $ psql -c "DROP users_retired" $PGSLICE_URL  

Далее токмо надо топтать ради в количестве партиций. Для сего команду pgslice add_partitions не возбраняется прибросить в cron:

  # day 0 0 * * * pgslice add_partitions <table> --future 0 --url ...  # month 0 0 0 * * pgslice add_partitions <table> --future 0 --url ...  

Заключение

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

Репликация

Введение

Репликация (англ. replication) — орудие синхронизации содержимого нескольких копий объекта (например, содержимого базы данных). Репликация — сие процесс, лещадь которым понимается размножение данных с одного источника получи и распишись пропасть других да наоборот. При репликации изменения, сделанные в одной копии объекта, могут фигурировать распространены в часть копии. Репликация может являться синхронной иначе говоря асинхронной.

В случае синхронной репликации, ежели данная возражение обновляется, до сей времени прочие реплики того а фрагмента данных тоже должны присутствовать обновлены в одной да пирушка но транзакции. Логически сие означает, что такое? существует как только одна разновидность данных. В большинстве продуктов синхронная синтез реализуется вместе с через триггерных процедур (возможно, скрытых равным образом управляемых системой). Но синхронная аутосинтез имеет оный недостаток, сколько симпатия создаёт дополнительную нагрузку рядом выполнении всех транзакций, в которых обновляются какие-либо реплики (кроме того, могут подыматься проблемы, связанные из доступностью данных).

В случае асинхронной репликации освежение одной реплики распространяется получи и распишись иные после некоторое время, а безвыгодный в праздник а транзакции. Таким образом, рядом асинхронной репликации вводится задержка, сиречь сезон ожидания, в поток которого отдельные реплики могут оказываться действительно неидентичными (то поглощать атрибуция замечание в действительности невыгодный абсолютно подходящим, ибо да мы со тобой невыгодный имеем мастерство не без; точными равно актуально созданными копиями). В большинстве продуктов асинхронная аутосинтез реализуется путем чтения журнала транзакций сиречь постоянной очереди тех обновлений, которые подлежат распространению. Преимущество асинхронной репликации состоит в том, сколько дополнительные затрата репликации никак не связаны из транзакциями обновлений, которые могут держать важное ценность интересах функционирования общем предприятия равно представлять высокие спрос для производительности. К недостаткам этой схемы относится то, который показатели могут попасть несовместимыми (то убирать несовместимыми не без; точки зрения пользователя). Иными словами, чрезмерность может представляться сверху логическом уровне, а это, сурово говоря, означает, что-то антилогарифм контролируемая чрезмерность в таком случае безвыгодный применим.

Рассмотрим коротко проблему согласованности (или, скорее, несогласованности). Дело в том, аюшки? реплики могут превращаться несовместимыми в результате ситуаций, которые тяжело (или даже если невозможно) избежать да последствия которых нелегко исправить. В частности, конфликты могут происходить до поводу того, в каком порядке должны использоваться обновления. Например, предположим, зачем в результате выполнения транзакции А происходит помещение строки в реплику X, за а транзакция B удаляет эту строку, а тоже допустим, ась? Y — возражение X. Если обновления распространяются держи Y, же вводятся в реплику Y в обратном порядке (например, ради разных задержек быть передаче), ведь транзакция B невыгодный находит в Y строку, подлежащую удалению, равно малограмотный выполняет своё действие, со временем что-что транзакция А вставляет эту строку. Суммарный коэффициент полезного действия состоит в том, почто оттиск Y заключает указанную строку, а тирада X — нет.

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

Основное неравенство в среде репликацией равным образом управлением копированием заключается в следующем: даже если используется репликация, ведь реконструирование одной реплики в конечном счёте распространяется получай всё-таки накипь автоматически. В режиме управления копированием, напротив, далеко не существует такого автоматического распространения обновлений. Копии данных создаются равно управляются со через пакетного либо — либо фонового процесса, какой-никакой отделён нет слов времени через транзакций обновления. Управление копированием в общем паче с полной отдачей за сравнению со репликацией, потому что после безраздельно присест могут копироваться взрослые объёмы данных. К недостаткам дозволено отнести то, в чем дело? большую делянка времени копии данных малограмотный идентичны базовым данным, благодаря тому пользователи должны учитывать, в отдельных случаях не кто иной были синхронизированы сии данные. Обычно господство копированием упрощается по причине тому требованию, дай тебе обновления применялись в соответствии со схемой первичной копии того иначе говоря иного вида.

Для репликации PostgreSQL существует ряд решений, наравне закрытых, в такой мере равно свободных. Закрытые системы репликации далеко не будут рассматриваться в этой книге. Вот перечень свободных решений:

Это, конечно, малограмотный огульно опись свободных систем к репликации, только ажно изо сего очищать ась? выкроить ради PostgreSQL.

Потоковая удвоение (Streaming Replication)

Потоковая синтез (Streaming Replication, SR) дает вероятность непрерывно заниматься равно ставить на службу WAL (Write-Ahead Log) дневной журнал держи резервные сервера для того создания точной копии текущего. Данная функциональность появилась у PostgreSQL начиная из 0 версии. Этот фигура репликации простой, доказанный и, вероятней всего, короче применяться в качестве стандартной репликации в большинстве высоконагруженных приложений, ась? используют PostgreSQL.

Отличительными особенностями решения являются:

К недостаткам дозволено отнести:

Установка

Для основные принципы нам потребуется PostgreSQL отнюдь не дальше 0 версии. Все работы, на правах полагается, будут проводится возьми Linux.

Настройка

Обозначим умелец сервер наравне masterdb(192.168.0.10) да слейв по образу slavedb(192.168.0.20) .

Предварительная конфиги

Для основания позволим определенному пользователю безо пароля грясти сообразно ssh. Пусть сие бросьте postgres юзер. Если но нет, так создаем набором команд:

  $ sudo groupadd userssh $ sudo useradd -m -g userssh -d /home/userssh -s /bin/bash \ -c "user ssh allow" userssh  

Дальше выполняем команды через имени пользователя (в данном случае postgres ):

  $ su postgres  

Генерим RSA-ключ чтобы обеспечения аутентификации в условиях отсутствия потенциал проэксплуатировать пароль:

  $ ssh-keygen -t rsa -P "" Generating public/private rsa key pair. Enter file in which to save the key (/var/lib/postgresql/.ssh/id_rsa): Created directory '/var/lib/postgresql/.ssh'. Your identification has been saved in /var/lib/postgresql/.ssh/id_rsa. Your public key has been saved in /var/lib/postgresql/.ssh/id_rsa.pub. The key fingerprint is: 16:08:27:97:21:39:b5:7b:86:e1:46:97:bf:12:3d:76 postgres@localhost  

И добавляем его в перечень авторизованных ключей:

  $ cat $HOME/.ssh/id_rsa.pub » $HOME/.ssh/authorized_keys  

Проверить дееспособность соединения дозволяется нетрудно написав:

  $ ssh localhost  

Не забываем до инициализировать sshd :

  $ $/etc/init.d/sshd start  

После успешно проделаной операции скопируйте $HOME/.ssh держи slavedb . Теперь пишущий сии строки должны держать выполнимость помимо пароля входить от мастера нате слейв да со слейва держи спец путем ssh.

Также отредактируем pg_hba.conf держи мастере равно слейве, разрешив им кореш ко другу ход сверх пароля (тут добавляется дело replication ):

  host replication all 092.168.0.20/32 trust  
  host replication all 092.168.0.10/32 trust  

Не забываем затем сего переместить postgresql держи обеих серверах.

Настройка мастера

Для альфа и омега настроим masterdb. Установим габариты в postgresql.conf к репликации:

  # To enable read-only queries on a standby server, wal_level must be set to # "hot_standby". But you can choose "archive" if you never connect to the # server in standby mode. wal_level=hot_standby  # Set the maximum number of concurrent connections from the standby servers. max_wal_senders=5  # To prevent the primary server from removing the WAL segments required for # the standby server before shipping them, set the minimum number of segments # retained in the pg_xlog directory. At least wal_keep_segments should be # larger than the number of segments generated between the beginning of # online-backup and the startup of streaming replication. If you enable WAL # archiving to an archive directory accessible from the standby, this may # not be necessary. wal_keep_segments=32  # Enable WAL archiving on the primary to an archive directory accessible from # the standby. If wal_keep_segments is a high enough number to retain the WAL # segments required for the standby server, this may not be necessary. archive_mode=on archive_command='cp %p /path_to/archive/%f'  

Давайте объединение порядку:

По умолчанию редупликация асинхронная. В версии 0.1 добавили параметр synchronous_standby_names , который-нибудь заключает синхронную репликацию. В сведения параметр передается application_name , кой используется сверху слейвах в recovery.conf :

  restore_command='cp /mnt/server/archivedir/%f %p' # e.g. 'cp /mnt/server/archivedir/%f %p' standby_mode=on primary_conninfo='host=masterdb port=59121 user=replication password=replication application_name=newcluster' # e.g. 'host=localhost port=5432' trigger_file='/tmp/trig_f_newcluster'  

После изменения параметров перегружаем PostgreSQL сервер. Теперь перейдем для slavedb .

Настройка слейва

Для альфа и омега нам потребуется учредить получи и распишись slavedb точную копию masterdb . Перенесем документация из через «Онлайн бэкапа».

Переместимся нате masterdb сервер равным образом выполним в консоли:

  $ psql -c "SELECT pg_start_backup('label', true)"  

Теперь нам нужно перетащить сведения со мастера сверху слейв. Выполняем нате мастере:

  $ rsync -C -a --delete -e ssh --exclude postgresql.conf --exclude postmaster.pid \ --exclude postmaster.opts --exclude pg_log --exclude pg_xlog \ --exclude recovery.conf master_db_datadir/ slavedb_host:slave_db_datadir/  

идеже

После копирования данных не без; мастера возьми слейв, остановим онлайн бэкап. Выполняем держи мастере:

  $ psql -c "SELECT pg_stop_backup()"  

Для версии PostgreSQL 0.1+ допускается воспользоватся командой pg_basebackup (копирует базу получай slavedb подобным образом):

  $ pg_basebackup -R -D /srv/pgsql/standby --host=192.168.0.10 --port=5432  

Устанавливаем такие а сведения в конфиге postgresql.conf , аюшки? равно у мастера (чтобы рядом падении мастера слейв был в состоянии его заменить). Так а установим пополнительный параметр:

  hot_standby=on  

Внимание! Если нате мастере поставили wal_level=archive , в этом случае параметр оставляем сообразно умолчанию ( hot_standby=off ).

Далее возьми slavedb в директории не без; данными PostgreSQL создадим обложка recovery.conf не без; таким содержимым:

  # Specifies whether to start the server as a standby. In streaming replication, # this parameter must to be set to on. standby_mode='on'  # Specifies a connection string which is used for the standby server to connect # with the primary. primary_conninfo='host=192.168.0.10 port=5432 user=postgres'  # Specifies a trigger file whose presence should cause streaming replication to # end (i.e., failover). trigger_file='/path_to/trigger'  # Specifies a command to load archive segments from the WAL archive. If # wal_keep_segments is a high enough number to retain the WAL segments # required for the standby server, this may not be necessary. But # a large workload can cause segments to be recycled before the standby # is fully synchronized, requiring you to start again from a new base backup. restore_command='scp masterdb_host:/path_to/archive/%f "%p"'  

идеже

Теперь можем засунуть PostgreSQL в slavedb .

Тестирование репликации

В результате можем глянуть неразвитие слейвов ото мастера из через таких команд:

  $ psql -c "SELECT pg_current_xlog_location()" -h192.168.0.10 (masterdb)  pg_current_xlog_location --------------------------  0/2000000 (1 row)  $ psql -c "select pg_last_xlog_receive_location()" -h192.168.0.20 (slavedb)  pg_last_xlog_receive_location -------------------------------  0/2000000 (1 row)  $ psql -c "select pg_last_xlog_replay_location()" -h192.168.0.20 (slavedb)  pg_last_xlog_replay_location ------------------------------  0/2000000 (1 row)  

Начиная из версии 0.1 добавили дополнительные view с целью просмотра состояния репликации. Теперь master знает целое состояния slaves:

  # SELECT * from pg_stat_replication ;  procpid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | state | sent_location | write_location | flush_location | replay_location | sync_priority | sync_state  ---------+----------+-------------+------------------+-------------+-----------------+-------------+------------------------------+-----------+---------------+----------------+----------------+-----------------+---------------+------------  07135 | 06671 | replication | newcluster | 027.0.0.1 | | 03745 | 0011-05-22 08:13:04.19283+02 | streaming | 0/30008750 | 0/30008750 | 0/30008750 | 0/30008750 | 0 | sync  

Также со версии 0.1 добавили view pg_stat_database_conflicts , со через которой получи слейв базах не грех пролистать как запросов было отменено да за каким причинам:

  # SELECT * from pg_stat_database_conflicts ;  datid | datname | confl_tablespace | confl_lock | confl_snapshot | confl_bufferpin | confl_deadlock  -------+-----------+------------------+------------+----------------+-----------------+----------------  0 | template1 | 0 | 0 | 0 | 0 | 0  01979 | template0 | 0 | 0 | 0 | 0 | 0  01987 | postgres | 0 | 0 | 0 | 0 | 0  06384 | marc | 0 | 0 | 0 | 0 | 0  

Еще испытать работу репликации дозволено от через утилиты ps :

  $ ps -ef | grep sender postgres 0879 0831 0 00:31 ? 00:00:00 postgres: wal sender process postgres 027.0.0.1(44663) streaming 0/2000000  [slavedb] $ ps -ef | grep receiver postgres 0878 0872 0 00:31 ? 00:00:01 postgres: wal receiver process streaming 0/2000000  

Давайте проверим реприкацию равно выполним возьми мастере:

  $ psql test_db test_db=# create table test3(id int not null primary key,name varchar(20)); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test3_pkey" for table "test3" CREATE TABLE test_db=# insert into test3(id, name) values('1', 'test1'); INSERT 0 0 test_db=#  

Теперь проверим держи слейве результат:

  $ psql test_db test_db=# select * from test3;  id | name ----+-------  0 | test1 (1 row)  

Как видим, рамка от данными успешно скопирована не без; мастера в слейв. Более до мелочей по части настройке данной репликации позволительно дорожить изо официальной wiki .

Общие задачи

Переключение держи слейв подле падении мастера

Достаточно основать триггер обложка ( trigger_file ) бери слейве, тот или другой перестанет скандовать исходняк вместе с мастера.

Остановка репликации сверху слейве

Создать триггер обложка ( trigger_file ) нате слейве. Также от версии 0.1 добавили функции pg_xlog_replay_pause() равно pg_xlog_replay_resume() чтобы остановки равным образом возобновления репликации.

Перезапуск репликации позже сбоя

Повторяем операции с раздела «». Хочется заметить, что такое? спец близ этом отнюдь не нуждается в остановке возле выполнении данной задачи.

Перезапуск репликации со временем сбоя слейва

Перезагрузить PostgreSQL в слейве позже устранения сбоя.

Повторно хронировать репликации в слейве

Это может потребоваться, например, затем длительного отключения через мастера. Для сего останавливаем PostgreSQL в слейве равным образом повторяем операции изо раздела «».

Repmgr

Repmgr  — подбор инструментов в целях управления потоковой репликацией равным образом восстановления по прошествии сбоя кластера PostgreSQL серверов. Он автоматизирует настройку резервных серверов, наблюдение репликации, а в свою очередь помогает делать задачи администрированию кластера, такие по образу отказоустойчивость (failover) или — или перекидывание мастера-слейва (слейв становится мастером, а умелец - слейвом). Repmgr работает от версии PostgreSQL 0.3 равно выше.

Repmgr состоит с двух утилит:

Пример использования: автоматическое переход слейва в артист

Для использования failover потребуется присыпать repmgr_funcs в postgresql.conf :

  shared_preload_libraries='repmgr_funcs'  

И приплюсовать настройки в repmgr.conf :

  failover=automatic promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file' follow_command='repmgr standby follow -f /etc/repmgr.conf --log-to-file'  

Для демонстрации автоматического failover, настроен кластер вместе с тремя узлами репликации (один виртуоз равно двуха слейв сервера), где-то что-нибудь матрица repl_nodes выглядит следующим образом:

  # SELECT id, type, upstream_node_id, priority, active FROM repmgr_test.repl_nodes ORDER BY id;  id | type | upstream_node_id | priority | active ----+---------+------------------+----------+--------  0 | master | | 000 | t  0 | standby | 0 | 000 | t  0 | standby | 0 | 000 | t (3 rows)  

После запуска repmgrd демона для каждом сервере в режиме ожидания, убеждаемся что-нибудь некто мониторит кластер:

  checking cluster configuration with schema 'repmgr_test' [2016-01-05 03:15:40] [INFO] checking node 0 in cluster 'test' [2016-01-05 03:15:40] [INFO] reloading configuration file and updating repmgr tables [2016-01-05 03:15:40] [INFO] starting continuous standby node monitoring  

Теперь остановим штукарь базу:

  pg_ctl -D /path/to/node1/data -m immediate stop  

repmgrd механично замечает снижение мастера да переключает нераздельно изо слейвов в мастер:

  connection to upstream has been lost, trying to recover... 05 seconds before failover decision [2016-01-06 08:33:03] [WARNING] connection to upstream has been lost, trying to recover... 00 seconds before failover decision [2016-01-06 08:33:08] [WARNING] connection to upstream has been lost, trying to recover... 0 seconds before failover decision ... [2016-01-06 08:33:18] [NOTICE] this node is the best candidate to be the new master, promoting... ... [2016-01-06 08:33:20] [NOTICE] STANDBY PROMOTE successful  

Также переключает оставшийся слейв для свежеиспеченный мастер:

  connection to upstream has been lost, trying to recover... 05 seconds before failover decision [2016-01-06 08:33:03] [WARNING] connection to upstream has been lost, trying to recover... 00 seconds before failover decision [2016-01-06 08:33:08] [WARNING] connection to upstream has been lost, trying to recover... 0 seconds before failover decision ... [2016-01-06 08:33:23] [NOTICE] node 0 is the best candidate for new master, attempting to follow... [2016-01-06 08:33:23] [INFO] changing standby's master ... [2016-01-06 08:33:25] [NOTICE] node 0 now following new upstream node 0  

Таблица repl_nodes короче обновлена, так чтобы воспроизвести новую ситуацию — архаический искусник node1 помечен наравне неактивный, равно слейв node3 нынче работает с нового мастера node2 :

  # SELECT id, type, upstream_node_id, priority, active from repl_nodes ORDER BY id;  id | type | upstream_node_id | priority | active ----+---------+------------------+----------+--------  0 | master | | 000 | f  0 | master | | 000 | t  0 | standby | 0 | 000 | t (3 rows)  

В таблицу repl_events будут добавлены склерозник того, аюшки? содеялось со каждым сервером изумительный эпоха failover:

  # SELECT node_id, event, successful, details from repmgr_test.repl_events where event_timestamp>='2016-01-06 08:30';  node_id | event | successful | details ---------+--------------------------+------------+----------------------------------------------------------  0 | standby_promote | t | node 0 was successfully promoted to master  0 | repmgrd_failover_promote | t | node 0 promoted to master; old master 0 marked as failed  0 | repmgrd_failover_follow | t | node 0 now following new upstream node 0 (3 rows)  

Заключение

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

Patroni

Patroni  — сие кентавр для Python, позволяющий автоматично прислуживать кластеры PostgreSQL из потоковой репликацией.

Особенности:

Информация по части настройке да использованию Patroni находится в официальной документации проекта.

Stolon

Stolon  — сие ночница в Go, позволяющий безотчетно эксплуатировать кластеры PostgreSQL из потоковой репликацией.

Особенности:

Stolon состоит с 0 основных компонентов:

Информация до настройке равно использованию Stolon находится в официальной документации проекта.

PostgreSQL Bi-Directional Replication (BDR)

BDR (Bi-Directional Replication) сие новая функциональность добавленая в опора PostgreSQL которая предоставляет расширенные капитал для того репликации. На текущий пора сие реализовано в виде небольшого патча равно модуля пользу кого 0.4 версии. Заявлено сколько совершенно хорэ исключительно в PostgreSQL 0.6 (разработчики решили никак не упражняться поддержкой патча интересах 0.5, а встретиться для прирост патчей в непосредственно PostgreSQL). BDR позволяет основывать географически распределенные асинхронные мульти-мастер конфигурации используя в целях сего встроенную логическую потоковую репликацию LLSR (Logical Log Streaming Replication).

BDR малограмотный является инструментом пользу кого кластеризации, т.к. на этом месте вышел каких-либо глобальных менеджеров блокировок иначе координаторов транзакций. Каждый блок безграмотный зависит ото других, почто было бы не по мнению плечу в случае использования менеджеров блокировки. Каждый с узлов охватывает локальную копию данных идентичную данным сверху других узлах. Запросы опять же выполняются всего лишь локально. При этом первый попавшийся с узлов про себя консистентен в что придется время, вдрызг но ряд серверов является согласованной в конечном счете (eventually consistent). Уникальность BDR заключается в книга почто симпатия непохожа ни сверху встроенную потоковую репликацию, ни в существующие trigger-based решения (Londiste, Slony, Bucardo).

Самым заметным отличием с потоковой репликации является то, почто BDR (LLSR) оперирует базами (per-database replication), а классическая PLSR реплицирует вдрызг инстанс (per-cluster replication), т.е. всё-таки базы в середке инстанса. Существующие ограничения да особенности:

Небольшое примечание: временная замедление репликации осуществляется выключением downstream мастера. Однако игра стоит свеч затронуть что такое? остановленная тирада приводит ко тому что такое? upstream виртуоз продолжит копить WAL журналы сколько в свою черед может обусловить для неконтролируемому расходу пространства получи и распишись диске. Поэтому здорово невыгодный рекомендуется на долгое время сливать реплику. Удаление реплики всегда осуществляется вследствие исключение конфигурации BDR возьми downstream сервере со последующим перезапуском downstream мастера. Затем нужно вырвать согласующий слот репликации возьми upstream мастере вместе с через функции pg_drop_replication_slot("slotname") . Доступные слоты не грех проюрдонить из через функции pg_get_replication_slots .

На обыдённый час сконцентрировать BDR не грех с исходников по части данному мануалу . С официальным принятием данных патчей в сердечник PostgreSQL установленный раздел ради BDR полноте расширен равным образом дополнен.

Pglogical

Pglogical  — сие расколачивание пользу кого PostgreSQL, которое использует логическое расшифровка помощью publish/subscribe модель. Данное рост базируется для BDR проекте ([sec:bdr] ). Расширение работает всего-навсего начиная вместе с версии PostgreSQL 0.4 равным образом вне (из-за логического декодирования). Для разных вариаций обнаружения равно разрешения конфликтов должно модификация 0.5 да выше.

Используются следующие термины в целях описания pglogical:

Сценарии использования pglogical:

Архитектурные детали:

Установка да набор

Установить pglogical дозволяется по мнению данной документации . Далее должно настроить последовательный декодинг в PostgreSQL:

  wal_level='logical' max_worker_processes=10 # one per database needed on provider node  # one per node needed on subscriber node max_replication_slots=10 # one per node needed on provider node max_wal_senders=10 # one per node needed on provider node shared_preload_libraries='pglogical'  

Если используется PostgreSQL 0.5+ равным образом нужно машины разрешения конфликтов, ведь нужно подложить дополнительные опции:

  track_commit_timestamp=on # needed for last/first update wins conflict resolution  # property available in PostgreSQL 0.5+  

В pg_hba.conf нужно дозволить replication соеденения со локального хоста к пользователя со привилегией репликации. После перезапуска базы нужно активировать пополнение бери всех нодах:

  CREATE EXTENSION pglogical;  

Далее возьми master (мастер) создаем provider (процесс, кто хорэ изменять изменения ради subscriber-ов) ноду:

  SELECT pglogical.create_node(  node_name :='provider1',  dsn :='host=providerhost port=5432 dbname=db' );  

И добавляем однако таблицы в public схеме:

  SELECT pglogical.replication_set_add_all_tables('default', ARRAY['public']);  

Далее переходим сверху slave (слейв) равным образом создаем subscriber ноду:

  SELECT pglogical.create_node(  node_name :='subscriber1',  dsn :='host=thishost port=5432 dbname=db' );  

После сего создаем «подписку» сверху provider ноду, которая начнет синхронизацию да репликацию в фоне:

  SELECT pglogical.create_subscription(  subscription_name :='subscription1',  provider_dsn :='host=providerhost port=5432 dbname=db' );  

Если по сию пору проделано верно, subscriber чрез строгий расстояние времени subscriber нода должна извлечь точную копию всех таблиц в public схеме вместе с master хоста.

Разрешение конфликтов

Если используется схема, идеже subscriber нода подписана для способности с нескольких provider-ов, иначе говоря а для subscriber факультативно производятся локальные изменения данных, могут просыпаться конфликты на новых изменений. В pglogical встроен устройство на обнаружения равно разрешения конфликтов. Настройка данного механизма происходит вследствие pglogical.conflict_resolution ключ. Поддерживаются следующие значения:

Когда опция track_commit_timestamp отключена, единственное допустимое достоинство в целях pglogical.conflict_resolution может присутствовать apply_remote . Поскольку track_commit_timestamp невыгодный доступен в PostgreSQL 0.4, данная опция установлена по части умолчанию в apply_remote .

Ограничения да бедность

Slony-I

Slony сие концепция репликации реального времени, позволяющая образовать синхронизацию нескольких серверов PostgreSQL сообразно сети. Slony использует триггеры PostgreSQL интересах привязки ко событиям INSERT/DELETE/UPDATE да хранимые процедуры в целях выполнения действий.

Система Slony не без; точки зрения администратора состоит изо двух главных компонент: репликационного демона slony равно административной рента slonik . Администрирование системы сводится для общению со slonik -ом, дух slon токмо следит вслед по сути дела процессом репликации.

Все команды slonik принимает получи частный stdin. До альфа и омега выполнения скрипт slonik-a проверяется держи корреспонденция синтаксису, разве обнаруживаются ошибки, скрипт малограмотный выполняется, этак сколько позволяется отнюдь не беспокоиться когда slonik сообщает относительно syntax error, ни ложки страшного малограмотный произошло. И спирт ещё шиш отнюдь не сделал. Скорее всего.

Установка

Установка получи Ubuntu производится бездействие командой:

  $ sudo aptitude install slony1-2-bin  

Настройка

Рассмотрим установку бери гипотетическую базу данных customers. Исходные данные:

Подготовка master базы

Для основные положения нужно сложить пользователя в базе, по-под которым склифосовский поступать Slony. По умолчанию, равно отдавая должное системе, сего пользователя по большей части называют slony.

  $ createuser -a -d slony $ psql -d template1 -c "ALTER USER slony WITH PASSWORD 'slony_user_password';"  

Также сверху каждом с узлов паче возбудить системного пользователя slony, с тем вонзать с его имени репликационного демона slon. В дальнейшем подразумевается, почто некто (и юзер да slon) поглощать нате каждом изо узлов кластера.

Подготовка slave базы

Здесь рассматривается, ась? серверы кластера соединены при помощи сети. Необходимо так чтобы не без; каждого изо серверов позволено было определить переплетение от PostgreSQL бери master хосте, равным образом наоборот. То есть, команда:

  anyuser@customers_slave$ psql -d customers \ -h customers_master.com -U slony  

должна подсоединять нас для мастер-серверу (после ввода пароля, желательно).

Теперь устанавливаем для slave-хост сервер PostgreSQL. Следующего как всегда никак не требуется, приёмом по прошествии установки Postgres «up and ready», так в случае каких-то ошибок позволено начить «с чистого листа», выполнив следующие команды (предварительно сохранив конфигурационные файлы равным образом остановив postmaster):

  pgsql@customers_slave$ rm -rf $PGDATA pgsql@customers_slave$ mkdir $PGDATA pgsql@customers_slave$ initdb -E UTF8 -D $PGDATA pgsql@customers_slave$ createuser -a -d slony pgsql@customers_slave$ psql -d template1 -c "alter \ user slony with password 'slony_user_password';"  

Далее запускаем postmaster. Обычно надлежит определённый содержатель чтобы реплицируемой БД. В этом случае нуждаться основать его тоже:

  pgsql@customers_slave$ createuser -a -d customers_owner pgsql@customers_slave$ psql -d template1 -c "alter \ user customers_owner with password 'customers_owner_password';"  

Эти двум команды дозволяется начинать от customers_master , для командной строке в этом случае нужно присчитать -h customers_slave , с намерением целое операции выполнялись для slave.

На slave, во вкусе равным образом сверху master, в свой черед нужно учредить Slony.

Инициализация БД равным образом plpgsql держи slave

Следующие команды выполняются ото пользователя slony. Скорее только про выполнения каждой изо них потребуется завести фраза ( slony_user_password ):

  slony@customers_master$ createdb -O customers_owner \ -h customers_slave.com customers slony@customers_master$ createlang -d customers \ -h customers_slave.com plpgsql  

Внимание! Все таблицы, которые будут добавлены в replication set должны обладать primary key. Если какая-то с таблиц неграмотный удовлетворяет этому условию, задержитесь получай этом шаге равным образом выкладывай каждой таблице primary key командой ALTER TABLE ADD PRIMARY KEY . Если столбца тот или другой был в силах бы стоить primary key невыгодный находится, добавьте последний колонка будто serial ( ALTER TABLE ADD COLUMN ), да заполните его значениями. Настоятельно НЕ рекомендую эксплуатировать table add key slonik-a.

Далее создаём таблицы равно всё остальное держи slave базе:

  slony@customers_master$ pg_dump -s customers | \ psql -U slony -h customers_slave.com customers  

pg_dump -s сдампит токмо структуру нашей БД.

pg_dump -s customers обязан давать уйти кроме пароля, а вишь интересах psql -U slony -h customers_slave.com customers придётся накопить фраза ( slony_user_pass ). Важно: подразумевается что-нибудь не долго думая получай мастер-хосте ещё безвыгодный установлен Slony (речь безвыгодный ради make install ), так лакомиться в БД кто в отсутствии таблиц sl_* , триггеров равным образом прочего.

Инициализация кластера

Сейчас автор сих строк имеем двуха сервера PostgreSQL которые беспрепятственно «видят» товарищ друга до сети, сверху одном изо них находится мастер-база не без; данными, нате другом — токмо архитектура базы. Далее мастер-хосте запускаем скрипт:

  #!/bin/sh  CLUSTER=customers_rep  DBNAME1=customers DBNAME2=customers  HOST1=customers_master.com HOST2=customers_slave.com  PORT1=5432 PORT2=5432  SLONY_USER=slony  slonik «EOF cluster name=$CLUSTER; node 0 admin conninfo='dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_password'; node 0 admin conninfo='dbname=$DBNAME2 host=$HOST2 port=$PORT2 user=slony password=slony_user_password'; init cluster ( id=1, comment='Customers DB replication cluster' );  echo 'Create set';  create set ( id=1, origin=1, comment='Customers DB replication set' );  echo 'Adding tables to the subscription set';  echo ' Adding table public.customers_sales...'; set add table ( set id=1, origin=1, id=4, full qualified name='public.customers_sales', comment='Table public.customers_sales' ); echo ' done';  echo ' Adding table public.customers_something...'; set add table ( set id=1, origin=1, id=5, full qualified name='public.customers_something, comment='Table public.customers_something ); echo ' done';  echo 'done adding'; store node ( id=2, comment='Node 0, $HOST2' ); echo 'stored node'; store path ( server=1, client=2, conninfo='dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_password' ); echo 'stored path'; store path ( server=2, client=1, conninfo='dbname=$DBNAME2 host=$HOST2 port=$PORT2 user=slony password=slony_user_password' );  store listen ( origin=1, provider=1, receiver=2 ); store listen ( origin=2, provider=2, receiver=1 ); EOF  

Здесь инициализируется кластер, создается replication set, включаются в него двум таблицы. Нужно перебрать безвыездно таблицы, которые нужно реплицировать. Replication set запоминается однова да навсегда. Чтобы прибросить блок в схему репликации никак не нужно сначала инициализировать set. Если в коллекция добавляется либо удаляется рамка нужно переподписать однако узлы. То лакомиться содеять unsubscribe равным образом subscribe заново.

Подписываем slave-узел в replication set

Далее запускаем в слейве:

  #!/bin/sh  CLUSTER=customers_rep  DBNAME1=customers DBNAME2=customers  HOST1=customers_master.com HOST2=customers_slave.com  PORT1=5432 PORT2=5432  SLONY_USER=slony  slonik «EOF cluster name=$CLUSTER; node 0 admin conninfo='dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_password'; node 0 admin conninfo='dbname=$DBNAME2 host=$HOST2 port=$PORT2 user=slony password=slony_user_password';  echo'subscribing'; subscribe set ( id=1, provider=1, receiver=2, forward=no);  EOF  

Старт репликации

Теперь, для обеих узлах ничего не поделаешь пустить демона репликации.

  slony@customers_master$ slon customers_rep \ "dbname=customers user=slony"  

да

  slony@customers_slave$ slon customers_rep \ "dbname=customers user=slony"  

Cлоны обменяются сообщениями равно начнут передачу данных. Начальное обуревание происходит из через COPY команды, слейв трест в сие момент совсем блокируется.

Общие задачи

Добавление ещё одного узла в работающую схему репликации

Требуется привести в исполнение [subsec:slonyI-settings-1] да [subsec:slonyI-settings-2] этапы. Новый прибор имеет id=3. Находится сверху хосте customers_slave3.com , «видит» мастер-сервер согласно узы равным образом ремесленник может включиться для его PostgreSQL. После дублирования структуры (п [subsec:slonyI-settings].2) делается следующее:

  slonik «EOF cluster name=customers_slave; node 0 admin conninfo='dbname=customers host=customers_slave3.com port=5432 user=slony password=slony_user_pass'; uninstall node (id=3); echo 'okay'; EOF  

Это нужно с намерением услать схему, триггеры равно процедуры, которые были сдублированы совместно вместе с таблицами равно структурой БД. Инициализировать кластер никак не надо. Вместо сего записываем информацию об новом узле в сети:

  #!/bin/sh  CLUSTER=customers_rep  DBNAME1=customers DBNAME3=customers  HOST1=customers_master.com HOST3=customers_slave3.com  PORT1=5432 PORT2=5432  SLONY_USER=slony  slonik «EOF cluster name=$CLUSTER; node 0 admin conninfo='dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_pass'; node 0 admin conninfo='dbname=$DBNAME3 host=$HOST3 port=$PORT2 user=slony password=slony_user_pass';  echo 'done adding';  store node ( id=3, comment='Node 0, $HOST3' ); echo 'sored node'; store path ( server=1, client=3, conninfo='dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_pass' ); echo 'stored path'; store path ( server=3, client=1, conninfo='dbname=$DBNAME3 host=$HOST3 port=$PORT2 user=slony password=slony_user_pass' );  echo 'again'; store listen ( origin=1, provider=1, receiver=3 ); store listen ( origin=3, provider=3, receiver=1 );  EOF  

Новый шарнир имеет id 0, благодаря чего что-нибудь 0 сделано работает. Подписываем новомодный секция 0 получи replication set:

  #!/bin/sh  CLUSTER=customers_rep  DBNAME1=customers DBNAME3=customers  HOST1=customers_master.com HOST3=customers_slave3.com  PORT1=5432 PORT2=5432  SLONY_USER=slony  slonik «EOF cluster name=$CLUSTER; node 0 admin conninfo='dbname=$DBNAME1 host=$HOST1 port=$PORT1 user=slony password=slony_user_pass'; node 0 admin conninfo='dbname=$DBNAME3 host=$HOST3 port=$PORT2 user=slony password=slony_user_pass';  echo'subscribing'; subscribe set ( id=1, provider=1, receiver=3, forward=no);  EOF  

Теперь запускаем slon возьми новом узле, таково но во вкусе да получи остальных. Перезапускать slon сверху мастере далеко не надо.

  slony@customers_slave3$ slon customers_rep \ "dbname=customers user=slony"  

Репликация должна подступить равно как обычно.

Устранение неисправностей

Ошибка подле добавлении узла в систему репликации

Периодически, возле добавлении новой аппаратура в кластер возникает следующая ошибка: держи новой ноде всё начинает дудеть в одну дудку да работать, имеющиеся но отваливаются от приближённо следующей диагностикой:

  %slon customers_rep "dbname=customers user=slony_user" CONFIG main: slon version 0.0.5 starting up CONFIG main: local node id=3 CONFIG main: loading current cluster configuration CONFIG storeNode: no_id=1 no_comment='CustomersDB replication cluster' CONFIG storeNode: no_id=2 no_comment='Node 0, node2.example.com' CONFIG storeNode: no_id=4 no_comment='Node 0, node4.example.com' CONFIG storePath: pa_server=1 pa_client=3 pa_conninfo="dbname=customers host=mainhost.com port=5432 user=slony_user password=slony_user_pass" pa_connretry=10 CONFIG storeListen: li_origin=1 li_receiver=3 li_provider=1 CONFIG storeSet: set_id=1 set_origin=1 set_comment='CustomersDB replication set' WARN remoteWorker_wakeup: node 0 - no worker thread CONFIG storeSubscribe: sub_set=1 sub_provider=1 sub_forward='f' WARN remoteWorker_wakeup: node 0 - no worker thread CONFIG enableSubscription: sub_set=1 WARN remoteWorker_wakeup: node 0 - no worker thread CONFIG main: configuration complete - starting threads CONFIG enableNode: no_id=1 CONFIG enableNode: no_id=2 CONFIG enableNode: no_id=4 ERROR remoteWorkerThread_1: "begin transaction; set transaction isolation level serializable; lock table "_customers_rep".sl_config_lock; select "_customers_rep".enableSubscription(1, 0, 0); notify "_customers_rep_Event"; notify "_customers_rep_Confirm"; insert into "_customers_rep".sl_event (ev_origin, ev_seqno, ev_timestamp, ev_minxid, ev_maxxid, ev_xip, ev_type , ev_data1, ev_data2, ev_data3, ev_data4 ) values ('1', '219440', '2005-05-05 08:52:42.708351', '52501283', '52501292', '''52501283''', 'ENABLE_SUBSCRIPTION', '1', '1', '4', 'f'); insert into "_customers_rep". sl_confirm (con_origin, con_received, con_seqno, con_timestamp) values (1, 0, '219440', CURRENT_TIMESTAMP); commit transaction;" PGRES_FATAL_ERROR ERROR: insert or update on table "sl_subscribe" violates foreign key constraint "sl_subscribe-sl_path-ref" DETAIL: Key (sub_provider,sub_receiver)=(1,4) is not present in table "sl_path". INFO remoteListenThread_1: disconnecting from 'dbname=customers host=mainhost.com port=5432 user=slony_user password=slony_user_pass' %  

Это означает сколько в служебной таблице _<имя кластера>.sl_path , так _customers_rep.sl_path получи еще имеющихся узлах нет как нет исходны данные насчёт новом узле. В данном случае, id нового узла 0, близнецы (1,4) в sl_path отсутствует. Чтобы сие устранить, нужно облечь в мясо и кровь возьми каждом изо имеющихся узлов так нижеуказанный запрос:

  $ psql -d customers -h _every_one_of_slaves -U slony customers=# insert into _customers_rep.sl_path values ('1','4','dbname=customers host=mainhost.com port=5432 user=slony_user password=slony_user_password,'10');  

Если возникают затруднения, ведь не запрещается осмотреть бери служебные таблицы равно их содержимое. Они безвыгодный видны по большей части да находятся в рамках пространства имён _<имя кластера> , на выдержку _customers_rep .

Что вытворять разве повторение со временем начинает не давать ходу

В процессе эксплуатации может наблюдатся по образу со временем растёт работа для master-сервере, в списке активных бекендов — постоянные SELECT-ы со слейвов. В pg_stat_activity видны почти такие запросы:

  select ev_origin, ev_seqno, ev_timestamp, ev_minxid, ev_maxxid, ev_xip, ev_type, ev_data1, ev_data2, ev_data3, ev_data4, ev_data5, ev_data6, ev_data7, ev_data8 from "_customers_rep".sl_event e where (e.ev_origin='2' and e.ev_seqno > '336996') or (e.ev_origin='3' and e.ev_seqno > '1712871') or (e.ev_origin='4' and e.ev_seqno > '721285') or (e.ev_origin='5' and e.ev_seqno > '807715') or (e.ev_origin='1' and e.ev_seqno > '3544763') or (e.ev_origin='6' and e.ev_seqno > '2529445') or (e.ev_origin='7' and e.ev_seqno > '2512532') or (e.ev_origin='8' and e.ev_seqno > '2500418') or (e.ev_origin='10' and e.ev_seqno > '1692318') order by e.ev_origin, e.ev_seqno;  

идеже _customers_rep  — фамилия схемы с примера. Таблица sl_event отчего-то разрастается со временем, с большими паузами создавание сих запросов по неприемлемого времени. Удаляем ненужные записи:

  delete from _customers_rep.sl_event where ev_timestamp<NOW()-'1 DAY'::interval;  

Производительность должна вернуться ко изначальным значениям. Возможно имеет суть надраить таблицы _customers_rep.sl_log_* идеже где бы звёздочки подставляются натуральные числа, очевидно объединение количеству репликационных сетов, что-то около аюшки? _customers_rep.sl_log_1 по правилам должна существовать.

Londiste

Londiste представляет из себя мотор интересах организации репликации, сложенный в языке Python. Основные принципы: незыблемость да дюжинность использования. Из-за сего данное вердикт имеет не в эдакий мере функциональности, нежели Slony-I. Londiste использует в качестве транспортного механизма очередность PgQ (описание сего больше нежели интересного проекта остается ради рамками данной главы, ибо возлюбленный представляет участие веселей для того низкоуровневых программистов баз данных, нежели с целью конечных пользователей — администраторов СУБД PostgreSQL). Отличительными особенностями решения являются:

К недостаткам дозволяется отнести:

Установка

Установка бросьте проводиться получи и распишись Debian сервере. Поскольку Londiste — сие дробь Skytools, в таком случае нам нужно устанавливать таковой пакет:

  % sudo aptitude install skytools  

В некоторых системнах блок может содержатся трансформация 0.x, которая безвыгодный поддерживает каскадную репликацию, отказоустойчивость(failover) да перекидывание в среде серверами (switchover). По этой причине симпатия никак не короче расматриваться. Скачать самую последнюю версию пакета допускается из официального сайта . На час написания главы последняя вариация была 0.2. Начнем установку:

  $ wget http://pgfoundry.org/frs/download.php/3622/skytools-3.2.tar.gz $ tar zxvf skytools-3.2.tar.gz $ cd skytools-3.2/ # пакеты ради сборки deb $ sudo aptitude install build-essential autoconf \ automake autotools-dev dh-make \ debhelper devscripts fakeroot xutils lintian pbuilder \ python-all-dev python-support xmlto asciidoc \ libevent-dev libpq-dev libtool # python-psycopg нужен к работы Londiste $ sudo aptitude install python-psycopg2 postgresql-server-dev-all # данной командой собираем deb пакет $ make deb $ cd http://postgresql.leopard.in.ua/ # ставим skytools $ dpkg -i *.deb  

Для других систем позволяется составить Skytools командами:

  $ ./configure $ make $ make install  

Далее проверяем точность установки:

  $ londiste3 -V londiste3, Skytools version 0.2 $ pgqd -V bad switch: usage: pgq-ticker [switches] config.file Switches:  -v Increase verbosity  -q No output to console  -d Daemonize  -h Show help  -V Show version  --ini Show sample config file  -s Stop - send SIGINT to running process  -k Kill - send SIGTERM to running process  -r Reload - send SIGHUP to running process  

Настройка

Обозначения:

Конфигурация репликаторов

Сначала создается конфигурационный обложка с целью master базы (конфиг бросьте /etc/skytools/master-londiste.ini ):

  job_name=master_l3simple db=dbname=l3simple queue_name=replika logfile=/var/log/skytools/master_l3simple.log pidfile=/var/pid/skytools/master_l3simple.pid  # Задержка в кругу проверками наличия активности # (новых пакетов данных) в секундах loop_delay=0.5  

Инициализируем Londiste в целях master базы:

  $ londiste3 /etc/skytools/master-londiste.ini create-root master-node "dbname=l3simple host=master-host" INFO plpgsql is installed INFO Installing pgq INFO Reading from /usr/share/skytools3/pgq.sql INFO pgq.get_batch_cursor is installed INFO Installing pgq_ext INFO Reading from /usr/share/skytools3/pgq_ext.sql INFO Installing pgq_node INFO Reading from /usr/share/skytools3/pgq_node.sql INFO Installing londiste INFO Reading from /usr/share/skytools3/londiste.sql INFO londiste.global_add_table is installed INFO Initializing node INFO Location registered INFO Node "master-node" initialized for queue "replika" with type "root" INFO Done  

идеже master-server  — сие наименование провайдера (мастера базы).

Теперь запустим демон:

  $ londiste3 -d /etc/skytools/master-londiste.ini worker $ tail -f /var/log/skytools/master_l3simple.log INFO {standby: 0} INFO {standby: 0}  

Если нужно переместить кентавр (например близ изменении конфигурации), в таком случае позволяется воспользоватся параметром -r :

  $ londiste3 /etc/skytools/master-londiste.ini -r  

Для остановки демона вкушать параметр -s :

  $ londiste3 /etc/skytools/master-londiste.ini -s  

либо разве потребуется «убить» ( kill ) демон:

  $ londiste3 /etc/skytools/master-londiste.ini -k  

Для автоматизации данного процесса skytools3 имеет замонтированный демон, тот или другой запускает весь воркеры с директории /etc/skytools/ . Сама схема демона находится в /etc/skytools.ini . Что бы включить всё-таки демоны londiste хватает выполнить:

  $ /etc/init.d/skytools3 start INFO Starting master_l3simple  

Перейдем ко slave базе. Для альфа и омега нужно организовать базу данных:

  $ psql -h slave1-host -U postgres # CREATE DATABASE l3simple;  

Подключение нужно бытийствовать «trust» (без паролей) в среде master равно slave базами данных.

Далее создадим конфиг для того slave базы ( /etc/skytools/slave1-londiste.ini ):

  job_name=slave1_l3simple db=dbname=l3simple queue_name=replika logfile=/var/log/skytools/slave1_l3simple.log pidfile=/var/pid/skytools/slave1_l3simple.pid  # Задержка посредь проверками наличия активности # (новых пакетов данных) в секундах loop_delay=0.5  

Инициализируем Londiste к slave базы:

  $ londiste3 /etc/skytools/slave1-londiste.ini create-leaf slave1-node "dbname=l3simple host=slave1-host" --provider="dbname=l3simple host=master-host"  

Теперь можем привести в действие демон:

  $ londiste3 -d /etc/skytools/slave1-londiste.ini worker  

Или а вследствие первостатейный демон:

  $ /etc/init.d/skytools3 start INFO Starting master_l3simple INFO Starting slave1_l3simple  

Создаём конфигурацию к PgQ ticker

Londiste надо PgQ ticker к работы со знаток базой данных, кто может являться запущен да держи разный машине. Но, конечно, отличается как небо через земли его шибать держи праздник же, идеже да master основа данных. Для сего автор настраиваем особливый конфиг пользу кого ticker демона (конфиг бросьте /etc/skytools/pgqd.ini ):

  logfile=/var/log/skytools/pgqd.log pidfile=/var/pid/skytools/pgqd.pid  

Запускаем демон:

  $ pgqd -d /etc/skytools/pgqd.ini $ tail -f /var/log/skytools/pgqd.log LOG Starting pgqd 0.2 LOG auto-detecting dbs ... LOG l3simple: pgq version ok: 0.2  

Или а посредством поголовный демон:

  $ /etc/init.d/skytools3 restart INFO Starting master_l3simple INFO Starting slave1_l3simple INFO Starting pgqd LOG Starting pgqd 0.2  

Теперь не возбраняется познать гражданское состояние кластера:

  $ londiste3 /etc/skytools/master-londiste.ini status Queue: replika Local node: slave1-node  master-node (root)  | Tables: 0/0/0  | Lag: 04s, Tick: 0  +--: slave1-node (leaf)  Tables: 0/0/0  Lag: 04s, Tick: 0  $ londiste3 /etc/skytools/master-londiste.ini members Member info on master-node@replika: node_name dead node_location --------------- --------------- -------------------------------- master-node False dbname=l3simple host=master-host slave1-node False dbname=l3simple host=slave1-host  

Но редупликация пока что безвыгодный запущенна: надо примолвить таблицы в очередь, которые наша сестра хотим реплицировать. Для сего используем команду add-table :

  $ londiste3 /etc/skytools/master-londiste.ini add-table --all $ londiste3 /etc/skytools/slave1-londiste.ini add-table --all --create-full  

В данном примере используется параметр --all , который-нибудь означает безвыездно таблицы, да на смену него вас можете назвать ведомость конкретных таблиц, ежели никак не хотите реплицировать все. Если имена таблиц отличаются для master да slave, так не грех пускать в ход --dest-table параметр рядом добавлении таблиц в slave базе. Также, если бы ваша милость малограмотный перенесли струкруру таблиц наперед вместе с master получи и распишись slave базы, в таком случае сие не запрещается произвести механично посредством --create параметр (или --create-full , неравно нужно перетащить совсем всю схему таблицы).

Подобным образом добавляем последовательности ( sequences ) для того репликации:

  $ londiste3 /etc/skytools/master-londiste.ini add-seq --all $ londiste3 /etc/skytools/slave1-londiste.ini add-seq --all  

Но последовательности должны в slave базе созданы рано (тут безграмотный поможет --create-full с целью таблиц). Поэтому порой уймись свести точную копию структуры master базы нате slave:

  $ pg_dump -s -npublic l3simple | psql -hslave1-host l3simple  

Далее проверяем имущество репликации:

  $ londiste3 /etc/skytools/master-londiste.ini status Queue: replika Local node: master-node  master-node (root)  | Tables: 0/0/0  | Lag: 08s, Tick: 02  +--: slave1-node (leaf)  Tables: 0/4/0  Lag: 08s, Tick: 02  

Как не возбраняется заметить, недалече «Table» содержится три цифры (x/y/z). Каждая обозначает:

Через маленький квинтдецима времени по сию пору таблицы должны синхронизироватся:

  $ londiste3 /etc/skytools/master-londiste.ini status Queue: replika Local node: master-node  master-node (root)  | Tables: 0/0/0  | Lag: 01s, Tick: 00  +--: slave1-node (leaf)  Tables: 0/0/0  Lag: 01s, Tick: 00  

Дополнительно Londiste позволяет пропускать ситуация таблиц да последовательностей возьми master да slave базах:

  $ londiste3 /etc/skytools/master-londiste.ini tables Tables on node table_name merge_state table_attrs ----------------------- --------------- --------------- public.pgbench_accounts ok public.pgbench_branches ok public.pgbench_history ok public.pgbench_tellers ok  $ londiste3 /etc/skytools/master-londiste.ini seqs Sequences on node seq_name local last_value ------------------------------ --------------- --------------- public.pgbench_history_hid_seq True 03345  

Проверка

Для проверки будем воспользоваться pgbench утилиту. Запустим прибавление данных в таблицу равным образом смотрим в логи одновлеменно:

  $ pgbench -T 00 -c 0 l3simple $ tail -f /var/log/skytools/slave1_l3simple.log INFO {count: 0508, duration: 0.307, idle: 0.0026} INFO {count: 0572, duration: 0.3085, idle: 0.002} INFO {count: 0600, duration: 0.3086, idle: 0.0026} INFO {count: 06, duration: 0.0157, idle: 0.0191}  

Как как автор этих строк погляжу соответственно логам slave склад успешно реплицируется вместе с master базой.

Каскадная ауторепродукция

Каскадная синтез позволяет реплицировать эмпирика из одного слейва возьми другой. Создадим конфиг с целью второго slave (конфиг довольно /etc/skytools/slave2-londiste.ini ):

  job_name=slave2_l3simple db=dbname=l3simple host=slave2-host queue_name=replika logfile=/var/log/skytools/slave2_l3simple.log pidfile=/var/pid/skytools/slave2_l3simple.pid  # Задержка в кругу проверками наличия активности # (новых пакетов данных) в секундах loop_delay=0.5  

Для создания slave, через которого не запрещается реплицировать отдельные люди базы данных используется главенство create-branch взамен create-leaf (root, стержень - master нода, предоставляет информацию к репликации; branch, отросток - нода со копией данных, со которой дозволено реплицировать; leaf, пластина - нода со копией данными, хотя реплицировать от нее уж отнюдь не возможно):

  $ psql -hslave2-host -d postgres -c "CREATE DATABASE l3simple;" $ pg_dump -s -npublic l3simple | psql -hslave2-host l3simple $ londiste3 /etc/skytools/slave2-londiste.ini create-branch slave2-node "dbname=l3simple host=slave2-host" --provider="dbname=l3simple host=master-host" INFO plpgsql is installed INFO Installing pgq INFO Reading from /usr/share/skytools3/pgq.sql INFO pgq.get_batch_cursor is installed INFO Installing pgq_ext INFO Reading from /usr/share/skytools3/pgq_ext.sql INFO Installing pgq_node INFO Reading from /usr/share/skytools3/pgq_node.sql INFO Installing londiste INFO Reading from /usr/share/skytools3/londiste.sql INFO londiste.global_add_table is installed INFO Initializing node INFO Location registered INFO Location registered INFO Subscriber registered: slave2-node INFO Location registered INFO Location registered INFO Location registered INFO Node "slave2-node" initialized for queue "replika" with type "branch" INFO Done  

Далее добавляем постоянно таблицы равным образом последовательности:

  $ londiste3 /etc/skytools/slave2-londiste.ini add-table --all $ londiste3 /etc/skytools/slave2-londiste.ini add-seq --all  

И запускаем небывалый демон:

  $ /etc/init.d/skytools3 start INFO Starting master_l3simple INFO Starting slave1_l3simple INFO Starting slave2_l3simple INFO Starting pgqd LOG Starting pgqd 0.2  

Повторим вышеперечисленные операции на slave3 равным образом slave4, лишь поменяем provider на них:

  $ londiste3 /etc/skytools/slave3-londiste.ini create-branch slave3-node "dbname=l3simple host=slave3-host" --provider="dbname=l3simple host=slave2-host" $ londiste3 /etc/skytools/slave4-londiste.ini create-branch slave4-node "dbname=l3simple host=slave4-host" --provider="dbname=l3simple host=slave3-host"  

В результате получаем такую картину вместе с кластером:

  $ londiste3 /etc/skytools/slave4-londiste.ini status Queue: replika Local node: slave4-node  master-node (root)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave1-node (leaf)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave2-node (branch)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave3-node (branch)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave4-node (branch)  Tables: 0/0/0  Lag: 0s, Tick: 09  

Londiste позволяет «на лету» переменять топологию кластера. Например, изменим «provider» про slave4:

  $ londiste3 /etc/skytools/slave4-londiste.ini change-provider --provider="dbname=l3simple host=slave2-host" $ londiste3 /etc/skytools/slave4-londiste.ini status Queue: replika Local node: slave4-node  master-node (root)  | Tables: 0/0/0  | Lag: 02s, Tick: 06  +--: slave1-node (leaf)  | Tables: 0/0/0  | Lag: 02s, Tick: 06  +--: slave2-node (branch)  | Tables: 0/0/0  | Lag: 02s, Tick: 06  +--: slave3-node (branch)  | Tables: 0/0/0  | Lag: 02s, Tick: 06  +--: slave4-node (branch)  Tables: 0/0/0  Lag: 02s, Tick: 06  

Также топологию дозволено выменивать от сторони репликатора вследствие команду takeover :

  $ londiste3 /etc/skytools/slave3-londiste.ini takeover slave4-node $ londiste3 /etc/skytools/slave4-londiste.ini status Queue: replika Local node: slave4-node  master-node (root)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave1-node (leaf)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave2-node (branch)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave3-node (branch)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave4-node (branch)  Tables: 0/0/0  Lag: 0s, Tick: 09  

Через команду drop-node позволяется спровадить slave с кластера:

  $ londiste3 /etc/skytools/slave4-londiste.ini drop-node slave4-node $ londiste3 /etc/skytools/slave3-londiste.ini status Queue: replika Local node: slave3-node  master-node (root)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave1-node (leaf)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave2-node (branch)  | Tables: 0/0/0  | Lag: 0s, Tick: 09  +--: slave3-node (branch)  Tables: 0/0/0  Lag: 0s, Tick: 09  

Команда tag-dead может использоваться, в чем дело? бы определить slave вроде безграмотный активный (прекратить получай него репликацию), а вследствие команду tag-alive его позволено отвоевать в кластер.

Общие задачи

Проверка состояния слейвов

Данный требование получи мастере дает некоторую информацию что касается каждой очереди равно слейве:

  # SELECT queue_name, consumer_name, lag, last_seen FROM pgq.get_consumer_info();  queue_name | consumer_name | lag | last_seen ------------+------------------------+-----------------+-----------------  replika | .global_watermark | 00:03:37.108259 | 00:02:33.013915  replika | slave1_l3simple | 00:00:32.631509 | 00:00:32.533911  replika | .slave1-node.watermark | 00:03:37.108259 | 00:03:05.01431  

идеже lag графа показывает гистерезис с мастера в синхронизации, last_seen  — эпоха последней запроса с слейва. Значение сего столбца безграмотный требуется присутствовать больше, нежели 00 секунд в целях конфигурации согласно умолчанию.

Удаление очереди всех событий изо мастера

При работе от Londiste может понадобиться спровадить всё-таки ваши настройки к того, с намерением заварить кашу до этого времени заново. Для PGQ, воеже остановить аккумуляция данных, используйте следующие API:

  SELECT pgq.unregister_consumer('queue_name', 'consumer_name');  

Добавление столбца в таблицу

Добавляем в следующей последовательности:

  1. прибавить нива сверху постоянно слейвы;

  2. BEGIN; – нате мастере;

  3. прибавить нива получай мастере;

  4. COMMIT;

Удаление столбца изо таблицы

  1. BEGIN; – нате мастере;

  2. спровадить луг в мастере;

  3. COMMIT;

  4. Проверить lag , в отдельных случаях londiste пройдет миг удаления поля;

  5. вырвать степь возьми всех слейвах;

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

Устранение неисправностей

Londiste пожирает вычислитель равным образом lag растет

Это происходит, например, коли вот сезон сбоя забыли перезапустить ticker. Или рано или поздно сделали больший UPDATE тож DELETE в одной транзакции, только ныне что такое? бы провести в жизнь каждое происшествие в этом запросе создаются транзакции бери слейвах …

Следующий интерпелляция позволяет подсчитать, сколь событий пришло в pgq.subscription в колонках sub_last_tick равно sub_next_tick .

  SELECT count(*)  FROM pgq.event_1,  (SELECT tick_snapshot  FROM pgq.tick  WHERE tick_id BETWEEN 0715138 AND 0715139  ) as t(snapshots) WHERE txid_visible_in_snapshot(ev_txid, snapshots);  

На практике сие было больше нежели 0 миллионов равно 000 тысяч событий. Чем свыше событий вместе с базы данных надлежит взбучить Londiste, тем чище ему надлежит памяти на этого. Возможно изречь Londiste отнюдь не занимать безвыездно действие сразу. Достаточно прирастить в INI конфиг PgQ ticker следующую настройку:

  pgq_lazy_fetch=500  

Теперь Londiste хорош захватывать красная стоимость в базарный день 000 событий в единодержавно сверток запросов. Остальные попадут в следующие пакеты запросов.

Bucardo

Bucardo  — асинхронная master-master тож master-slave синтез PostgreSQL, которая написана в Perl. Система архи гибкая, поддерживает серия видов синхронизации да обработки конфликтов.

Установка

Установка хорошенького понемножку проводиться сверху Debian сервере. Сначала нужно назначить DBIx::Safe Perl модуль.

  $ apt-get install libdbix-safe-perl  

Для других систем дозволительно обеспечить изо исходников :

  $ tar xvfz dbix_safe.tar.gz $ cd DBIx-Safe-1.2.5 $ perl Makefile.PL $ make $ make test $ sudo make install  

Теперь ставим самолично Bucardo. Скачиваем его равным образом инсталлируем:

  $ wget http://bucardo.org/downloads/Bucardo-5.4.1.tar.gz $ tar xvfz Bucardo-5.4.1.tar.gz $ cd Bucardo-5.4.1 $ perl Makefile.PL $ make $ sudo make install  

Для работы Bucardo потребуется поставить поддержку pl/perl языка в PostgreSQL.

  $ sudo aptitude install postgresql-plperl-9.5  

да дополнительные пакеты чтобы Perl (DBI, DBD::Pg, Test::Simple, boolean):

  $ sudo aptitude install libdbd-pg-perl libboolean-perl  

Теперь можем приниматься для настройке репликации.

Настройка

Инициализация Bucardo

Запускаем установку Bucardo:

  $ bucardo install  

Во промежуток времени установки будут показаны настройки подключения для PostgreSQL, которые позволяется довольно изменить:

  This will install the bucardo database into an existing Postgres cluster. Postgres must have been compiled with Perl support, and you must connect as a superuser  We will create a new superuser named 'bucardo', and make it the owner of a new database named 'bucardo'  Current connection settings: 1. Host: <none> 2. Port: 0432 3. User: postgres 4. Database: postgres 5. PID directory: /var/run/bucardo  

После подтверждения настроек, Bucardo создаст пользователя bucardo равно базу данных bucardo . Данный ламер обязан заключать законодательство логиниться при помощи Unix socket, благодаря тому отличается как небо ото земли рано наградить ему такие полномочия в pg_hda.conf .

После успешной установки позволительно обследовать конфигурацию вследствие команду bucardo show all :

  $ bucardo show all autosync_ddl=newcol bucardo_initial_version=5.0.0 bucardo_vac=1 bucardo_version=5.0.0 ctl_checkonkids_time=10 ctl_createkid_time=0.5 ctl_sleep=0.2 default_conflict_strategy=bucardo_latest  default_email_host=localhost  ...  

Настройка баз данных

Теперь нужно настроить базы данных, из которыми бросьте корпеть Bucardo. Обозначим базы в качестве кого master_db да slave_db . Реплицировать будем simple_database базу. Сначала настроим знаток базу:

  $ bucardo add db master_db dbname=simple_database host=master_host Added database "master_db"  

Данной командой указали базу данных да дали ей псевдоним master_db (для того, который в реальной жизни master_db равно slave_db имеют одинаковое имя базы simple_database равным образом их нужно выделять в Bucardo).

Дальше добавляем slave_db :

  $ bucardo add db slave_db dbname=simple_database port=5432 host=slave_host  

Настройка репликации

Теперь надо настроить синхронизацию посередь этими базами данных. Делается сие командой sync :

  $ bucardo add sync delta dbs=master_db:source,slave_db:target conflict_strategy=bucardo_latest tables=all Added sync "delta" Created a new relgroup named "delta" Created a new dbgroup named "delta"  Added table "public.pgbench_accounts"  Added table "public.pgbench_branches"  Added table "public.pgbench_history"  Added table "public.pgbench_tellers"  

Данная майна устанавливает Bucardo триггеры в PostgreSQL к master-slave репликации. Значения параметров:

Для master-master репликации надобно выполнить:

  $ bucardo add sync delta dbs=master_db:source,slave_db:source conflict_strategy=bucardo_latest tables=all  

Пример с целью создания master-master равным образом master-slave репликации:

  $ bucardo add sync delta dbs=master_db1:source,master_db2:source,slave_db1:target,slave_db2:target conflict_strategy=bucardo_latest tables=all  

Для проверки состояния репликации:

  $ bucardo status PID of Bucardo MCP: 02122  Name State Last good Time Last I/D Last bad Time =======+========+============+========+===========+===========+=======  delta | Good | 03:28:53 | 03m 0s | 0685/7384 | none |  

Запуск/Остановка репликации

Запуск репликации:

  $ bucardo start  

Остановка репликации:

  $ bucardo stop  

Общие задачи

Просмотр значений конфигурации

  $ bucardo show all  

Изменения значений конфигурации

  $ bucardo set name=value  

Например:

  $ bucardo_ctl set syslog_facility=LOG_LOCAL3  

Перегрузка конфигурации

  $ bucardo reload_config  

Более подробную информацию не грех выкопать сверху официальном сайте .

Репликация в оставшиеся типы баз данных

Начиная из версии 0.0 Bucardo поддерживает репликацию в оставшиеся библиография данных: drizzle, mongo, mysql, oracle, redis равно sqlite (тип базы задается около использовании команды bucardo add db путем родник «type», кой в соответствии с умолчанию postgres). Давайте рассмотрим прототип от redis базой. Для основы потребуется поставить redis звукосниматель к Perl (для других баз устанавливаются соответствующие):

  $ aptitude install libredis-perl  

Далее зарегистрируем redis базу в Bucardo:

  $ bucardo add db R dbname=simple_database type=redis Added database "R"  

Создадим группу баз данных по-под названием pg_to_redis :

  $ bucardo add dbgroup pg_to_redis master_db:source slave_db:source R:target Created dbgroup "pg_to_redis" Added database "master_db" to dbgroup "pg_to_redis" as source Added database "slave_db" to dbgroup "pg_to_redis" as source Added database "R" to dbgroup "pg_to_redis" as target  

И создадим репликацию:

  $ bucardo add sync pg_to_redis_sync tables=all dbs=pg_to_redis status=active Added sync "pg_to_redis_sync"  Added table "public.pgbench_accounts"  Added table "public.pgbench_branches"  Added table "public.pgbench_history"  Added table "public.pgbench_tellers"  

После перезапуска Bucardo эмпирика вместе с PostgreSQL таблиц начнуть реплицироватся в Redis:

  $ pgbench -T 00 -c 0 simple_database $ redis-cli monitor "HMSET" "pgbench_history:6" "bid" "2" "aid" "36291" "delta" "3716" "mtime" "2014-07-11 04:59:38.454824" "hid" "4331" "HMSET" "pgbench_history:2" "bid" "1" "aid" "65179" "delta" "2436" "mtime" "2014-07-11 04:59:38.500896" "hid" "4332" "HMSET" "pgbench_history:14" "bid" "2" "aid" "153001" "delta" "-264" "mtime" "2014-07-11 04:59:38.472706" "hid" "4333" "HMSET" "pgbench_history:15" "bid" "1" "aid" "195747" "delta" "-1671" "mtime" "2014-07-11 04:59:38.509839" "hid" "4334" "HMSET" "pgbench_history:3" "bid" "2" "aid" "147650" "delta" "3237" "mtime" "2014-07-11 04:59:38.489878" "hid" "4335" "HMSET" "pgbench_history:15" "bid" "1" "aid" "39521" "delta" "-2125" "mtime" "2014-07-11 04:59:38.526317" "hid" "4336" "HMSET" "pgbench_history:14" "bid" "2" "aid" "60105" "delta" "2555" "mtime" "2014-07-11 04:59:38.616935" "hid" "4337" "HMSET" "pgbench_history:15" "bid" "2" "aid" "186655" "delta" "930" "mtime" "2014-07-11 04:59:38.541296" "hid" "4338" "HMSET" "pgbench_history:15" "bid" "1" "aid" "101406" "delta" "668" "mtime" "2014-07-11 04:59:38.560971" "hid" "4339" "HMSET" "pgbench_history:15" "bid" "2" "aid" "126329" "delta" "-4236" "mtime" "2014-07-11 04:59:38.5907" "hid" "4340" "DEL" "pgbench_tellers:20"  

Данные в Redis хранятся в виде хешей:

  $ redis-cli "HGETALL" "pgbench_history:15"  0) "bid"  0) "2"  0) "aid"  0) "126329"  0) "delta"  0) "-4236"  0) "mtime"  0) "2014-07-11 04:59:38.5907"  0) "hid" 10) "4340"  

Также не запрещается подвергнуть проверке структура репликации:

  $ bucardo status PID of Bucardo MCP: 0655  Name State Last good Time Last I/D Last bad Time ==================+========+============+========+===========+===========+========  delta | Good | 04:59:39 | 0m 05s | 0/0 | none |  pg_to_redis_sync | Good | 04:59:40 | 0m 04s | 046/2546 | 04:59:39 | 0m 05s  

Теперь факты с redis могут употребляться к приложения в виде быстрого кэш хранилища.

Заключение

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

В главе было рассмотрено сколько-нибудь видов репликации PostgreSQL. Нельзя точно высказать какая отпустило всех. Потоковая репликация — единственный с самых лучших вариантов пользу кого поддержки идентичных кластеров баз данных. Slony-I — громоздкая да сложная в настройке система, да имеющая в своем арсенале пропасть функций, таких в духе отказоустойчивости (failover) равным образом перепрыгивание в обществе серверами (switchover). В также минута Londiste имея в своем арсенале сходный функционал, может похвастатся снова компактностью равно без затей в установке. Bucardo — налаженность которая может фигурировать или — или master-master, тож master-slave репликацией.

Шардинг

Введение

Шардинг — дробление данных получи уровне ресурсов. Концепция шардинга заключается в логическом разделении данных соответственно различным ресурсам, исходя изо требований ко нагрузке.

Рассмотрим пример. Пусть у нас кушать адденда не без; регистрацией пользователей, которое позволяет вносить дружище другу личные сообщения. Допустим оно адски популярно, да бессчётно людей им пользуются ежедневно. Естественно, в чем дело? матрица от личными сообщениями довольно стократ вяще всех остальных таблиц в базе (скажем, хорэ кредитоваться 00% всех ресурсов). Зная это, автор сих строк можем подготовить чтобы этой (только одной!) таблицы выкроенный сервер помощнее, а оставшиеся кончить нате другом (послабее). Теперь пишущий сии строки можем возвышенно подстроить сервер с целью работы из одной специфической таблицей, не пожалеть стараний поместить ее в память, возможно, в добавление партиционировать ее да т.д. Такое расположение называется вертикальным шардингом.

Что делать, буде наша сводка вместе с сообщениями стала в этакий мере большой, который аж выгороженный сервер подо нее одну сейчас безграмотный спасает? Необходимо выделывать горизонтальный шардинг — т.е. разграничение одной таблицы в соответствии с разным ресурсам. Как сие выглядит держи практике? На разных серверах у нас хорош сетка от одинаковой структурой, хотя разными данными. Для нашего случая из сообщениями, да мы от тобой можем сберегать первые 00 миллионов сообщений получи одном сервере, вторые 00 - сверху втором равно т.д. Т.е. что поделаешь обладать условие шардинга — какой-то параметр, какой-никакой позволит определять, возьми каком вот поэтому и есть сервере лежат те либо — либо кое-кто данные.

Обычно, в качестве параметра шардинга выбирают ID пользователя ( user_id ) — сие позволяет разрознивать показатели согласно серверам правильно да просто. Т.о. близ получении личных сообщений пользователей алгорифм работы полноте такой:

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

Естественно, делая горизонтальный шардинг, Вы ограничиваете себя в внутренние резервы выборок, которые требуют пересмотра всей таблицы (например, последние посты в блогах людей достаточно плешь переесть невозможно, коли список постов шардится). Такие задачи придется разрешать другими подходами. Например, ради описанного примера, не возбраняется подле появлении нового поста, вносить его ID в всесторонний стек, размером в 000 элементом.

Горизонтальный шардинг имеет одно явное преимущество — спирт долго масштабируем. Для создания шардинга PostgreSQL существует мало-мальски решений:

PL/Proxy

PL/Proxy представляет с лица прокси-язык с целью удаленного вызова процедур равным образом партицирования данных в обществе разными базами. Основная соображение его использования заключается в том, в чем дело? появляется допустимость бросать вызов функции, расположенные в удаленных базах, а в свою очередь безвозбранно сидеть вместе с кластером баз данных (например, затребовать функцию получи и распишись всех узлах кластера, сиречь получай случайном узле, alias держи каком-то одном определенном).

Чем PL/Proxy может присутствовать полезен? Он имеет первостепенное значение упрощает горизонтальное выбор масштаба системы. Становится удобным разводить таблицу со пользователями, например, в области первой латинской букве имени — сверху 06 узлов. При этом приложение, которое работает прямо со прокси-базой, ничто отнюдь не хорэ замечать: просьба бери авторизацию, например, самовластно короче направлен прокси-сервером возьми спешный узел. То кушать руководитель баз данных может вести выбор масштаба системы фактически беспричинно через разработчиков приложения.

PL/Proxy позволяет до конца хлопнуть проблемы масштабирования OLTP систем. В систему легко и просто вводится бронирование вместе с failover-ом малограмотный всего-навсего сообразно узлам, хотя да согласно самим прокси-серверам, отдельный с которых работает со всеми узлами.

Недостатки равным образом ограничения:

Установка

  1. Скачать PL/Proxy равным образом распаковать;

  2. Собрать PL/Proxy командами make равным образом make install ;

Так но дозволительно ввести PL/Proxy изо репозитория пакетов. Например в Ubuntu Server полно претворить команду про PostgreSQL 0.6:

  $ sudo aptitude install postgresql-9.6-plproxy  

Настройка

Для примера настройки используется 0 сервера PostgreSQL. 0 сервера нехай будут node1 равным образом node2 , а главный, сколько склифосовский проксировать требования для двум других — proxy . Для корректной работы pl/proxy рекомендуется эксплуатировать цифра нод равное степеням двойки. База данных хорошенького понемножку зваться plproxytest , а матрица в ней — users .

Для вводные положения настроим node1 да node2 . Команды, написанные ниже, нужно исполнять для каждой ноде. Сначала создадим базу данных plproxytest (если её ещё нет):

  CREATE DATABASE plproxytest  WITH OWNER=postgres  ENCODING='UTF8';  

Добавляем табличку users :

  CREATE TABLE public.users  (  username character varying(255),  email character varying(255)  )  WITH (OIDS=FALSE); ALTER TABLE public.users OWNER TO postgres;  

Теперь создадим функцию интересах добавления данных в таблицу users :

  CREATE OR REPLACE FUNCTION public.insert_user(i_username text, i_emailaddress text) RETURNS integer AS $BODY$ INSERT INTO public.users (username, email) VALUES ($1,$2);  SELECT 0; $BODY$  LANGUAGE 'sql' VOLATILE; ALTER FUNCTION public.insert_user(text, text) OWNER TO postgres;  

С настройкой нод закончено. Приступим для серверу proxy. Как да нате всех нодах, в главном сервере ( proxy ) должна фигурировать депо данных:

  CREATE DATABASE plproxytest  WITH OWNER=postgres  ENCODING='UTF8';  

Теперь полагается адресовать серверу сколько буква основа данных управляется от через pl/proxy:

  CREATE OR REPLACE FUNCTION public.plproxy_call_handler()  RETURNS language_handler AS '$libdir/plproxy', 'plproxy_call_handler'  LANGUAGE 'c' VOLATILE COST 0; ALTER FUNCTION public.plproxy_call_handler() OWNER TO postgres; -- language CREATE LANGUAGE plproxy HANDLER plproxy_call_handler; CREATE LANGUAGE plpgsql;  

Также, интересах того в чем дело? бы сервер знал идеже равно какие ноды у него есть, нужно сформировать 0 сервисные функции, которые pl/proxy достаточно пускать в дело в своей работе. Первая функция — конфиг для того кластера баз данных. Тут указываются мера вследствие key-value:

  CREATE OR REPLACE FUNCTION public.get_cluster_config (IN cluster_name text, OUT "key" text, OUT val text)  RETURNS SETOF record AS $BODY$ BEGIN  -- lets use same config for all clusters  key :='connection_lifetime';  val :=30*60; -- 00m  RETURN NEXT;  RETURN; END; $BODY$  LANGUAGE 'plpgsql' VOLATILE  COST 000  ROWS 0000; ALTER FUNCTION public.get_cluster_config(text) OWNER TO postgres;  

Вторая важная функция, шифр которой нужно короче подправить. В ней надлежит хорошенького понемножку установить DSN нод:

  CREATE OR REPLACE FUNCTION public.get_cluster_partitions(cluster_name text)  RETURNS SETOF text AS $BODY$ BEGIN  IF cluster_name='usercluster' THEN  RETURN NEXT 'dbname=plproxytest host=node1 user=postgres';  RETURN NEXT 'dbname=plproxytest host=node2 user=postgres';  RETURN;  END IF;  RAISE EXCEPTION 'Unknown cluster'; END; $BODY$  LANGUAGE 'plpgsql' VOLATILE  COST 000  ROWS 0000; ALTER FUNCTION public.get_cluster_partitions(text) OWNER TO postgres;  

И последняя:

  CREATE OR REPLACE FUNCTION public.get_cluster_version(cluster_name text)  RETURNS integer AS $BODY$ BEGIN  IF cluster_name='usercluster' THEN  RETURN 0;  END IF;  RAISE EXCEPTION 'Unknown cluster'; END; $BODY$  LANGUAGE 'plpgsql' VOLATILE  COST 000; ALTER FUNCTION public.get_cluster_version(text) OWNER TO postgres;  

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

  CREATE OR REPLACE FUNCTION public.insert_user(i_username text, i_emailaddress text)  RETURNS integer AS $BODY$  CLUSTER 'usercluster';  RUN ON hashtext(i_username); $BODY$  LANGUAGE 'plproxy' VOLATILE  COST 000; ALTER FUNCTION public.insert_user(text, text) OWNER TO postgres;  

Все готово. Подключаемся ко серверу proxy равным образом заносим показатели в базу:

  SELECT  SELECT insert_user('Marko',  SELECT  

Пробуем извлечь данные. Для сего напишем новую серверную функцию:

  CREATE OR REPLACE FUNCTION public.get_user_email(i_username text)  RETURNS SETOF text AS $BODY$  CLUSTER 'usercluster';  RUN ON hashtext(i_username) ;  SELECT email FROM public.users  WHERE username=i_username; $BODY$  LANGUAGE 'plproxy' VOLATILE  COST 000  ROWS 0000; ALTER FUNCTION public.get_user_email(text) OWNER TO postgres;  

И попробуем её вызвать:

  SELECT plproxy.get_user_email('Steve');  

Если далее включиться для каждой ноде отдельно, так дозволяется без запинки увидеть, который факты users разбросаны в соответствии с таблицам каждой ноды.

Все ли в такой мере просто?

Как различимо нате тестовом примере шиш сложного в работе вместе с pl/proxy нет. Но в реальной жизни до сей времени никак не таково просто. Представьте в чем дело? у вам 06 нод. Это а потребно однова хронировать адрес функций. А зачем разве неловкость закрадётся — что её производительно исправлять?

Этот проблема был задан да в конференции Highload++ 0008, бери что-нибудь Аско Ойя ответил ась? соответствующие собственность уж реализованы среди самого Skype, да ещё далеко не хватает готовы чтобы того что-то бы жертвовать чем их сверху суждение сообществу opensource.

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

Postgres-X2

Postgres-X2 – теория к создания мульти-мастер кластеров, работающих в синхронном режиме – всегда узлы век содержат актуальные данные. Postgres-X2 поддерживает опции чтобы увеличения масштабирования кластера вроде подле преобладании операций записи, что-то около равно около коренной нагрузке получи считка данных: поддерживается устройство транзакций от распараллеливанием получи мало-мальски узлов, вслед целостностью транзакций в пределах общем кластера отвечает сепаратный связка GTM (Global Transaction Manager).

Измерение производительности показало, почто полезное действие кластера Postgres-X2 составляет эталонно 04%, т.е. кластер изо 00 серверов позволяет вырвать увеличения производительности системы в целом в 0.4 раза, сравнительно производительности одного сервера (цифры приблизительные).

Система безграмотный использует в своей работе триггеры равно представляет на лицо пакет дополнений равно патчей ко PostgreSQL, дающих шанс в прозрачном режиме поставить работу в кластере стандартных приложений, кроме их дополнительной модификации равно адаптации (полная противоречивость не без; PostgreSQL API). Кластер состоит с одного управляющего узла (GTM), предоставляющего информацию касательно состоянии транзакций, равным образом произвольного набора рабочих узлов, произвольный изо которых в свою очередность состоит изо координатора равно обработчика данных (обычно сии простейшие положения реализуются бери одном сервере, а могут существовать да разделены).

Хоть Postgres-X2 да выглядит похожим возьми MultiMaster, так дьявол им далеко не является. Все сервера кластера должны существовать соединены сетью от минимальными задержками, никакое географически-распределенное постановление от разумной производительностью основать для нем не лещадь силу (это видный момент).

Архитектура

Рис. [fig:postgres-x21] показывает архитектуру Postgres-X2 вместе с тремя её основными компонентами:

  1. Глобальный предприниматель транзакций (GTM) — собирает да обрабатывает информацию относительно транзакциях в Postgres-X2, решает вопросы глобального идентификатора транзакции в соответствии с операциям (для поддержания согласованного представления базы данных получи всех узлах). Он обеспечивает поддержку других глобальных данных, таких по образу последовательности равно временные метки. Он хранит информация пользователя, следовать исключением управляющей информации;

  2. Координаторы (coordinators) — обеспечивают точку подключения с целью клиента (приложения). Они несут грех пополам следовать разделение да совершение запросов с клиентов равно отдание результатов (при необходимости). Они далеко не хранят пользовательские данные, а собирают их изо обработчиков данных (datanodes) вместе с через запросов SQL после PostgreSQL интерфейс. Координаторы вот и все обрабатывают данные, разве требуется, равно инда управляют двухфазной фиксацией. Координаторы используются да для того разбора запросов, составления планов запросов, поиска данных равно т.д;

  3. Обработчики данных (datanodes) — обеспечивают оберегание пользовательских данных. Datanodes выполняют требования ото координаторов да возвращают им высуженный результат;

Установка

Установить Postgres-X2 дозволено изо исходников .

Распределение данных равно масштабируемость

Postgres-X2 предусматривает двуха способа хранения данных в таблицах:

  1. Распределенные таблицы (distributed tables, рис. [fig:postgres-x22]): исходняк по мнению таблице распределяются получи и распишись определенный подбор обработчиков данных не без; использованием указанной стратегии (hash, round-robin, modulo). Каждая фанера в таблице находится всего лишь нате одном обработчике данных. Параллельно могут являться записаны сиречь прочитаны информация от различных обработчиков данных. За расчёт сего куда улучшена нагрузка возьми писание равно чтение;

  2. Реплицированные таблицы (replicated tables, рис. [fig:postgres-x23]): сведения объединение таблице реплицируется (клонируются) нате предуказанный сверток обработчиков данных. Каждая отметка в таблице находится держи всех обработчиках данных (которые были указаны) равно любые изменения дублируются получи и распишись совершенно обработчики данных. Так на правах всегда документация доступны сверху любом обработчике данных, фотокоординатор может составить до сей времени показатели с одного узла, сколько позволяет командировать неодинаковые требования для небо и земля обработчики данных. Таким образом создается компенсация нагрузки да увеличения пропускной данные для чтение;

Таблицы равным образом требования для ним

После установки вещь от Postgres-X2 положено в области штату как бы со обыкновенным PostgreSQL. Подключаться ради работы вместе с данными нужно всего-навсего ко координаторам (по умолчанию управленец работает получи и распишись порту 0432). Для основные положения создадим распределенные таблицы:

  CREATE TABLE users_with_hash (id SERIAL, type INT, ...) DISTRIBUTE by HASH(id);  CREATE TABLE users_with_modulo (id SERIAL, type INT, ...) DISTRIBUTE by MODULO(id);  CREATE TABLE users_with_rrobin (id SERIAL, type INT, ...) DISTRIBUTE by ROUNDROBIN;  

На листинге [lst:postgres-x22] создано 0 распределенные таблицы:

  1. Таблица users_with_hash распределяется соответственно хешу значения с указанного полина в таблице (тут замечено равнина id) по мнению обработчикам данных. Вот вроде распределились первые 05 значений:

      # координатор $ psql # SELECT id, type from users_with_hash ORDER BY id;  id | type -------+-------  0 | 046  0 | 053  0 | 084  0 | 022  0 | 085  0 | 006  0 | 073  0 | 099  0 | 034  00 | 086  01 | 035  02 | 0012  03 | 095  04 | 067  05 | 024  # центральный шлифовщик данных $ psql -p15432 # SELECT id, type from users_with_hash ORDER BY id;  id | type ------+-------  0 | 046  0 | 053  0 | 085  0 | 006  0 | 099  0 | 034  02 | 0012  03 | 095  05 | 024  # другой шлифовщик данных $ psql -p15433 # SELECT id, type from users_with_hash ORDER BY id;  id | type -------+-------  0 | 084  0 | 022  0 | 073  00 | 086  01 | 035  04 | 067  
  2. Таблица users_with_modulo распределяется по части модулю значения с указанного полина в таблице (тут отмечено равнина id) по части обработчикам данных. Вот равно как распределились первые 05 значений:

      # координатор $ psql # SELECT id, type from users_with_modulo ORDER BY id;  id | type -------+-------  0 | 083  0 | 019  0 | 09  0 | 038  0 | 063  0 | 046  0 | 040  0 | 031  0 | 084  00 | 099  01 | 08  02 | 091  03 | 045  04 | 076  05 | 060  # первоначальный шлифовщик данных $ psql -p15432 # SELECT id, type from users_with_modulo ORDER BY id;  id | type -------+-------  0 | 019  0 | 038  0 | 046  0 | 031  00 | 099  02 | 091  04 | 076  # дальнейший отделочник данных $ psql -p15433 # SELECT id, type from users_with_modulo ORDER BY id;  id | type ------+-------  0 | 083  0 | 09  0 | 063  0 | 040  0 | 084  01 | 08  03 | 045  05 | 060  
  3. Таблица users_with_rrobin распределяется циклическим способом(round-robin) в области обработчикам данных. Вот по образу распределились первые 05 значений:

      # координатор $ psql # SELECT id, type from users_with_rrobin ORDER BY id;  id | type -------+-------  0 | 090  0 | 098  0 | 015  0 | 046  0 | 01  0 | 037  0 | 048  0 | 046  0 | 096  00 | 022  01 | 042  02 | 095  03 | 014  04 | 040  05 | 033  # основной переработчик данных $ psql -p15432 # SELECT id, type from users_with_rrobin ORDER BY id;  id | type -------+-------  0 | 098  0 | 046  0 | 037  0 | 046  00 | 022  02 | 095  04 | 040  # следующий отделочник данных $ psql -p15433 # SELECT id, type from users_with_rrobin ORDER BY id;  id | type ------+-------  0 | 090  0 | 015  0 | 01  0 | 048  0 | 096  01 | 042  03 | 014  05 | 033  

Теперь создадим реплицированную таблицу:

  CREATE TABLE users_replicated (id SERIAL, type INT, ...) DISTRIBUTE by REPLICATION;  

Естественно исходняк идентичны для всех обработчиках данных:

  # SELECT id, type from users_replicated ORDER BY id;  id | type -------+-------  0 | 05  0 | 062  0 | 058  0 | 079  0 | 057  0 | 01  0 | 049  0 | 044  0 | 090  00 | 010  01 | 009  02 | 066  03 | 005  04 | 001  05 | 08  

Рассмотрим равно как выполняются требования пользу кого таблиц. Выберем постоянно ежедневник изо распределенной таблицы:

  # EXPLAIN VERBOSE SELECT * from users_with_modulo ORDER BY id;  QUERY PLAN --------------------------------------------------------------------------------------  Sort (cost=49.83..52.33 rows=1000 width=8)  Output: id, type  Sort Key: users_with_modulo.id  -> Result (cost=0.00..0.00 rows=1000 width=8)  Output: id, type  -> Data Node Scan on users_with_modulo (cost=0.00..0.00 rows=1000 width=8)  Output: id, type  Node/s: dn1, dn2  Remote query: SELECT id, type FROM ONLY users_with_modulo WHERE true (9 rows)  

Как различимо сверху листинге [lst:postgres-x26] фотокоординатор собирает причина изо обработчиков данных, а попозже собирает их вместе.

Подсчет фонды от группировкой в области полю с распределенной таблицы:

  # EXPLAIN VERBOSE SELECT sum(id) from users_with_modulo GROUP BY type;  QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------  HashAggregate (cost=5.00..5.01 rows=1 width=8)  Output: pg_catalog.sum((sum(users_with_modulo.id))), users_with_modulo.type  -> Materialize (cost=0.00..0.00 rows=0 width=0)  Output: (sum(users_with_modulo.id)), users_with_modulo.type  -> Data Node Scan on "__REMOTE_GROUP_QUERY__" (cost=0.00..0.00 rows=1000 width=8)  Output: sum(users_with_modulo.id), users_with_modulo.type  Node/s: dn1, dn2  Remote query: SELECT sum(group_1.id), group_1.type FROM (SELECT id, type FROM ONLY users_with_modulo WHERE true) group_1 GROUP BY 0 (8 rows)  

JOIN посреди равным образом из участием реплицированных таблиц, а в свой черед JOIN средь распределенными согласно одному равным образом тому но полю в таблицах склифосовский выполняются получай обработчиках данных. Но JOIN вместе с участием распределенных таблиц в области другим ключам будут выполнены сверху координаторе равным образом быстрее общем сие короче долго (листинг [lst:postgres-x28]).

  # EXPLAIN VERBOSE SELECT * from users_with_modulo, users_with_hash WHERE users_with_modulo.id=users_with_hash.id;  QUERY PLAN --------------------------------------------------------------------------------------------------  Nested Loop (cost=0.00..0.01 rows=1 width=16)  Output: users_with_modulo.id, users_with_modulo.type, users_with_hash.id, users_with_hash.type  Join Filter: (users_with_modulo.id=users_with_hash.id)  -> Data Node Scan on users_with_modulo (cost=0.00..0.00 rows=1000 width=8)  Output: users_with_modulo.id, users_with_modulo.type  Node/s: dn1, dn2  Remote query: SELECT id, type FROM ONLY users_with_modulo WHERE true  -> Data Node Scan on users_with_hash (cost=0.00..0.00 rows=1000 width=8)  Output: users_with_hash.id, users_with_hash.type  Node/s: dn1, dn2  Remote query: SELECT id, type FROM ONLY users_with_hash WHERE true (11 rows)  

Пример извлечение данных изо реплицированной таблицы:

  # EXPLAIN VERBOSE SELECT * from users_replicated;  QUERY PLAN ----------------------------------------------------------------------------  Data Node Scan on "__REMOTE_FQS_QUERY__" (cost=0.00..0.00 rows=0 width=0)  Output: users_replicated.id, users_replicated.type  Node/s: dn1  Remote query: SELECT id, type FROM users_replicated (4 rows)  

Как приметно изо запроса в целях отрывок данных используется единодержавно переработчик данных, а безвыгодный до сей времени (что логично).

Высокая элементарность (HA)

По архитектуре у Postgres-X2 постоянно лакомиться слаженность данных. По теореме CAP в таковой системе трудно послужить гарантией высокую доступность. Для успехи высокой доступности в распределенных системах надо чрезмерность данных, резервные копии равным образом автоматическое восстановление. В Postgres-X2 излишек данных может бытийствовать достигнута со через PostgreSQL потоковой (streaming) репликации со hot-standby чтобы обработчиков данных. Каждый организатор станет заносить равным образом заглядывать исходняк самостоятельно с другого, почему координаторы способны сменять дружище друга. Поскольку GTM единичный эксплуатация да может останавливаться точкой отказа, самое лучшее построить GTM-standby в духе резервную копию. Ну а вишь ради автоматического восстановления придется пускать в дело сторонние утилиты.

Ограничения

  1. Postgres-X2 базируется сверху PostgreSQL 0.3;

  2. Нет системы репартиционирования подле добавлении тож удалении нод;

  3. Нет глобальных UNIQUE держи распределенных таблицах;

  4. Не поддерживаются foreign keys посредь нодами поелику экий разъяснение надо возглавлять держи причина расположенные получи фолиант но обработчике данных;

  5. Не поддерживаются курсоры;

  6. Не поддерживается INSERT ... RETURNING ;

  7. Невозможно уничтожение равным образом добавка нод в кластер не принимая во внимание полной реинициализации кластера;

Заключение

Postgres-X2 архи перспективное урегулирование в целях организация кластера держи основе PostgreSQL. И на худой конец сие вердикт имеет линия недостатков, нестабильно (очень часты случаи падения координаторов быть тяжелых запросах) равным образом единаче куда молодое, со временем сие уступка может конституция стандартом пользу кого масштабирования систем получи PostgreSQL.

Postgres-XL

Postgres-XL – концепция интересах создания мульти-мастер кластеров, работающих в синхронном режиме – целое узлы век содержат актуальные данные. Проект построен возьми основе кодовой базы Postgres-X2, почему артитектурный путь вполне идентичен (глобальный администратор транзакций (GTM), координаторы (coordinators) равно обработчики данных (datanodes)). Более до мельчайших подробностей насчет архитектуру позволяется обожать в «[sec:postgres-x2-architecture] » разделе. Поэтому рассмотрим всего лента Postgres-X2 равным образом Postgres-XL.

Postgres-X2 равно Postgres-XL

Одно изо главных отличий Postgres-XL через Postgres-X2 является усовершенствованный уловка массово-параллельной архитектуры (massive parallel processing, MPP). Чтобы осознать разницу, давайте рассмотрим в духе Postgres-X2 равно Postgres-XL достаточно подвергать обработке непохожие SQL запросы. Оба сих кластера будут иметь на иждивении три таблицы T1 , T2 да R1 . T1 имеет колонки a1 равным образом a2 , T2  — b1 равно b2 . T1 распределена в кластере объединение a1 полю равно T2 распределена за b1 полю. R1 матрица имеет колонки c1 да c2 да реплицируется в кластере ( DISTRIBUTE by REPLICATION ).

Для начала, бесхитростный вопрос вида SELECT * FROM T1 короче паралельно происходить в нодах наравне у Postgres-X2, где-то да у Postgres-XL. Другой пояснение запроса SELECT * FROM T1 INNER JOIN R1 ON T1.a1=R1.c1 короче вдобавок материализовываться паралельно обоими кластерами, ибо сколько полноте передан («pushed down») в обработчики данных (datanodes) пользу кого выполнения равным образом управленец (coordinators) бросьте исключительно объединять (собирать) результаты запросов. Это достаточно потеть над чем по причине тому, почто R1 сетка дублицируется получи каждом обработчике данных. Этот образец запросов достаточно корпеть хорошо, когда-когда T1 является таблицей фактов (основной таблицей хранилища данных), в ведь момент в качестве кого R1  — таблицей измерений (содержит атрибуты событий, сохраненных в таблице фактов).

Теперь рассмотрим иной вид SQL запроса:

  # SELECT * FROM T1 INNER JOIN T2 ON T1.a1=T2.b2  

Данный задание делает JOIN объединение распределенной колонке a1 в таблице T1 равно по мнению НЕ распределенной колонке b2 в таблице T2 . В кластере, некоторый состоит изо 0 обработчиков данных, колонка в таблице T1 в первом с них потенциально необходимо рассеять от колонками таблицы T2 получи всех обработчиках данных в кластере.

У Postgres-X2 в данном случае обработчики данных отправляют совершенно сведения по мнению заданому условию в запросе для координатору, какой равно занимается объединением данных от таблиц. В данном примере слыхом не слыхивать критерий WHERE , ась? значит, в чем дело? совершенно обработчики данных отправят всегда содержание таблиц T1 равным образом T2 для координатор, который-нибудь равно короче совершать JOIN данных. В данной операции полноте блистать своим отсутствием паралельное совершение JOIN запроса равно будут дополнительные накладные затраты получи доставку всех данных ко координатору. Поэтому в данном случае Postgres-X2 на поверку хорош медленее, нежели действие подобного запроса держи обычном PostgreSQL сервере (особенно, разве таблицы ахти большие).

Postgres-XL хорош приготовлять схожий интерпелляция по-другому. Условие T1.a1=T2.b2 говорит по отношению том, почто я объединяем колонку b2 от колонкой a1 , которая является ключом распределения ради таблицы T1 . Поэтому, выбрав значения полина b2 , кластер короче по правилам видеть интересах каких обработчиков данных надлежит полученый следствие для того объединения от таблицей T1 (поскольку вроде приспособить хеш функцию распределения в полученые значения). Поэтому весь круг шлифовальщик данных считает со другого обработчика данных требуемые причина сообразно таблице T2 интересах объединения со своей таблицей T1 минус участия координатора. Данная вероятность откровенный коммуникации обработчиков данных со другими обработчиками данных позволяет распараллеливать больше сложные требования в Postgres-XL.

Postgres-XL имеет в свой черед некоторые улучшения производительности (более оптимально обрабатываются последовательности, прочее).

Заключение

Postgres-XL - вновь одно перспективное постановление на создания кластера получи и распишись основе Postgres-X2. Разработчики данного решения чище нацелены нате усовершенствование производительности да стабильности кластера, на смену добавления нового функционала.

Citus

Citus  — лежа масштабируемый PostgreSQL кластер. Citus использует устройство расширений PostgreSQL взамен того, что такое? бы проэксплуатировать модифицированную версию базы (как сие делает «[sec:postgres-x2] » тож «[sec:postgres-xl] »), ась? позволяет утилизировать новые версии PostgreSQL со новыми возможностями, сохраняя возле этом противоречие не без; существующими PostgreSQL инструментами. Кластер предоставляет пользователям результаты запросов в режиме «реального времени» чтобы большого равно растущего обьема данных (благодаря параллелизации запросов средь нодами). Примеры использования:

Нагрузки, которые требуют немаленький сель данных посередь узлами кластера, в качестве кого правило, отнюдь не хорош недурственно потеть над чем со Citus кластером. Например:

Архитектура

На верхнем уровне Citus кластер распределяет исходняк объединение PostgreSQL экземплярам. Входящие SQL требования по прошествии времени обрабатываются наплевать вследствие сии сервера.

При разворачивании кластера единственный изо экземпляров PostgreSQL выбирается в качестве художник (master) ноды. Затем другие добавляются как бы PostgreSQL воркеры (worker) в конфигурационном файле искусник ноды. После сего всегда сольватация вместе с кластером положено после ремесленник ноду не без; через стандартных PostgreSQL интерфейсов. Все материал распределены соответственно воркерам. Мастер хранит лишь только метаданные касательно воркерах.

Citus использует модульную архитектуру с целью блоков данных, которая похожа сверху HDFS (Hadoop Distributed File System), так использует PostgreSQL таблицы заместо файлов. Каждая изо сих таблиц представляет внешне горизонтальный раздел не так — не то неслучайный «шард» (shard). Каждый шард дублируется, за крайней мере, получи и распишись двух воркерах (можно настроить для сильнее высокое значение). В результате, разор одной механизмы безвыгодный влияет для отчётливость данных. Логическая зодчество шардинга в Citus вдобавок позволяет конкатенировать новые воркеры, с намерением расширить пропускную ловкость да вычислительную отдача кластера.

Citus штуцер заключает таблицы метаданных с целью отслеживания всех воркеров да предрасположенность шардов базы данных в них. Эти таблицы тоже ведут статистику, такую равно как размер равным образом минимальное/максимальное значений в шардах, которые помогают распределению SQL запросов Citus планировщику. Таблицы метаданных небольшие (обычно порядочно мегабайт), равно могут состоять дублированы да борзо восстановлены, кабы от мастером как-нибудь произойдет сбой. Подробнее в рассуждении таблицах метаданных допускается взглянуть в документации .

Когда кластер получает SQL запрос, Citus штукарь делит его держи побольше мелкие фрагменты запросов, идеже и оный и другой кусок может происходить самобытно держи воркере. Это позволяет Citus определять первый попавшийся интерпелляция в кластере, используя вычислительные мощности всех задействованных узлов, а в свой черед отдельных ядер возьми каждом узле. Мастер по времени поручает воркерам исполнить запрос, осуществляет ревизия вслед за их исполнением, объединяет результаты в соответствии с запросам да возвращает заключительный вывод пользователю. Для того, так чтобы гарантировать, что-то целое требования выполняются в масштабируемой манере, искусник и применяет оптимизации, которые сводят для минимуму величина данных, передаваемых согласно сети.

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

Установка

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

  postgres=# select * from master_get_active_worker_nodes();  node_name | node_port -----------+-----------  localhost | 0702  localhost | 0701 (2 rows)  

Распределенные таблицы

Каждая распределенная матрица в Citus включает стоблец, некоторый вынужден бытовать выбран в качестве значения на распределения объединение шардам (возможно облюбовать только лишь сам столбец). Это информирует базу данных по образу сберегать статистику равно сортировать требования за кластеру. Как правило, необходимо подобрать столбец, тот или иной является в особенности не раз используемым в запросах WHERE . В таком случае запросы, которые в фильтре используют сей столбец, будут делаться в шардах, которые выбираются соответственно условию фильтрации. Это помогает стократ понизить контингент вычислений получи и распишись шардах.

Следующим шажком по прошествии выбора столбца получай распределения полноте распознавание правильного метода распределения данных в таблицу. В целом, существует пара шаблона таблиц: распределенные согласно времени (время создания заказа, фанера логов, прочее) равно раздача в области идентификатору (ID пользователя, ID приложения, прочее). Citus поддерживает что один метода распределения: append да hash соответственно.

Append прием идет чтобы таблиц, в которые записываются показатели по части времени (упорядочены сообразно времени). Такой фрукт таблиц подходяще справляется из запросами, которые использут фильтры вместе с диапазонами значений согласно распределенному столбцу ( BETWEEN x AND y ). Это обьясняется тем, что такое? ремесленник хранит диапазоны значений, которые хранятся держи шардах, равно выравниватель может производительно предпочитать шарды, которые содержат информация в целях SQL запроса.

Hash схема распределения идет интересах неупорядоченного столбца (user UUID) либо объединение данным, которые могут заноситься в любом порядке. В таком случае Citus кластер достаточно оберегать минимальные да максимальные значения к хеш функций для всех шардах. Эта трафарет полегче к лицу с целью SQL запросов, включающих фильтры получай основе равенства в области колонке распределения ( user_uuid="a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11" ).

Hash дележ

Для примера создадим да распределим таблицу в соответствии с hash методу.

  # CREATE TABLE github_events (  event_id bigint,  event_type text,  event_public boolean,  repo_id bigint,  payload jsonb,  repo jsonb,  actor jsonb,  org jsonb,  created_at timestamp );  

Далее укажем Citus кластеру воспользоваться repo_id со hash распределением в целях github_events таблицы.

  # SELECT master_create_distributed_table('github_events', 'repo_id', 'hash');  

И создадим шарды чтобы таблицы:

  # SELECT master_create_worker_shards('github_events', 06, 0);  

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

Далее наша сестра можем охватить таблицу данными:

  $ wget http://examples.citusdata.com/github_archive/github_events-2015-01-01-{0..5}.csv.gz $ gzip -d github_events-2015-01-01-*.gz  
  # \COPY github_events FROM 'github_events-2015-01-01-0.csv' WITH (format CSV) # INSERT INTO github_events VALUES (2489373118,'PublicEvent','t',24509048,'{}','{"id": 04509048, "url": "https://api.github.com/repos/SabinaS/csee6868", "name": "SabinaS/csee6868"}','{"id": 0955009, "url": "https://api.github.com/users/SabinaS", "login": "SabinaS", "avatar_url": "https://avatars.githubusercontent.com/u/2955009?", "gravatar_id": ""}',NULL,'2015-01-01 00:09:13');  

Теперь ты да я можем сбрызгивать живой водой равным образом отлучать документация от таблицы:

  # UPDATE github_events SET org=NULL WHERE repo_id=24509048; # DELETE FROM github_events WHERE repo_id=24509048;  

Для работы UPDATE равным образом DELETE запросов требуется, в чем дело? бы возлюбленный «затрагивал» одиночный шард. Это означает, который соглашение WHERE следует вмещать условие, что-то ограничит исполнение запроса нате одиночный шард до распределенному столбцу. Для обновления не так — не то удаления данных держи нескольких шардах надлежит пустить в дело команду master_modify_multiple_shards :

  # SELECT master_modify_multiple_shards(  'DELETE FROM github_events WHERE repo_id IN (24509048, 04509049)');  

Для удаления таблицы хватает облечь плотью и кровью DROP TABLE получи и распишись мастере:

  # DROP TABLE github_events;  

Append распространение

Для примера создадим да распределим таблицу в области append методу.

  # CREATE TABLE github_events (  event_id bigint,  event_type text,  event_public boolean,  repo_id bigint,  payload jsonb,  repo jsonb,  actor jsonb,  org jsonb,  created_at timestamp );  

Далее укажем Citus кластеру пускать в дело created_at не без; append распределением с целью github_events таблицы.

  # SELECT master_create_distributed_table('github_events', 'created_at', 'append');  

После сего автор можем утилизировать таблицу да мудрить в нее данные:

  # SET citus.shard_max_size TO '64MB'; # \copy github_events from 'github_events-2015-01-01-0.csv' WITH (format CSV)  

По умолчанию повеление \copy требует двум конфигурационных параметра интересах работы: citus.shard_max_size равным образом citus.shard_replication_factor .

По умолчанию отряд \copy создает весь круг раз в год по обещанию новоявленный шард к данных. Если нужно прибавлять исходняк в единовластно да оный но шард, существуют команды master_create_empty_shard , которая вернет идентификатор получай недавний шард, да отряд master_append_table_to_shard в целях добавления данных в сей шард по части идентификатору.

Для удаления старых данных не возбраняется эксплуатировать команду master_apply_delete_command , которая удаляет старые шарды, которые попадают в переданное контракт получи удаление:

  # SELECT * from master_apply_delete_command('DELETE FROM github_events WHERE created_at >=''2015-01-01 00:00:00''');  master_apply_delete_command -----------------------------  0 (1 row)  

Для удаления таблицы шабаш воплотить в жизнь DROP TABLE сверху мастере:

  # DROP TABLE github_events;  

Ребалансировка кластера

Логическая зодчество шардинга Citus позволяет масштабировать кластер вне каких-либо простоев (no downtime!). Для добавления нового воркера стоит прибросить его в pg_worker_list.conf равно вытребовать получи мастере pg_reload_conf чтобы загрузки новой конфигурации:

  # SELECT pg_reload_conf();  

После сего Citus механически начнет эксплуатнуть известный воркер ради новых распределенных таблиц. Если надобно ребалансировать существующие таблицы получи и распишись новоиспеченный воркер, ведь интересах сего лакомиться распоряжение rebalance_table_shards , но, для сожалению, симпатия доступна всего только в Citus Enterprise (платное решение).

Ограничения

Модель расширения PostgreSQL в Citus позволяет эксплуатнуть доступные типы данных (JSON, JSONB, другие) да прочие расширения в кластере. Но безграмотный вполне спектр SQL запросов доступен чтобы распределенных таблиц. На нынешний пора распределенные таблицы неграмотный поддерживают:

Заключение

Citus кластер довольно гибкое равно мощное намерение интересах горизонтального масштабирования PostgreSQL. Зрелость данного решения показывает его применение такими игроками получи рынке, в духе CloudFlare, Heap равно многими другими.

Greenplum Database

Greenplum Database (GP)  — реляционная СУБД, имеющая массово-параллельную (massive parallel processing) архитектуру лишенный чего разделения ресурсов (shared nothing). Для подробного понимания принципов работы Greenplum нуждаться пометить основные термины:

В общем случае кластер GP состоит с нескольких серверов-сегментов, одного сервера-мастера, да одного сервера-секондари-мастера, соединённых средь на вывеску одной иначе несколькими быстрыми (10g, infiniband) сетями, обыкновенно обособленными (interconnect) (рис [fig:greenplum_arch1]).

Использование нескольких interconnect-сетей позволяет, во-первых, выдвинуть пропускную гений канала взаимодействия сегментов в обществе собой, да во-вторых, поставить отказоустойчивость кластера (в случае отказа одной с сетей полный затор перераспределяется в обществе оставшимися).

При выборе числа серверов-сегментов хоть куда безошибочно удосужиться паритет кластера «число процессоров/Тб данных» в зависимости с планируемого профиля нагрузки сверху БД — нежели чище процессорных ядер требуется держи единицу данных, тем быстрее кластер бросьте осуществлять «тяжёлые» операции, а в свой черед потеть над чем со сжатыми таблицами.

При выборе числа сегментов в кластере (которое в общем случае ко числу серверов никоим образом малограмотный привязано) делать нечего памятовать следующее:

Хранение данных

В Greenplum реализуется классическая диаграмма шардирования данных. Каждая схема представляет с себя N+1 таблиц бери всех сегментах кластера, идеже N — количество сегментов (+1 в этом случае — сие матрица получи мастере, данных в ней нет). На каждом сегменте хранится 0/N строк таблицы. Логика разбиения таблицы возьми сегменты задаётся ключом (полем) дистрибуции — таким полем, держи основе данных которого любую строку дозволительно отнести для одному изо сегментов.

Ключ (поле иначе пакет полей) дистрибуции — адски важное представление в GP. Как было сказано выше, Greenplum работает со скоростью самого медленного сегмента, сие означает, в чем дело? каждый неполадки в количестве данных (как в рамках одной таблицы, эдак да в рамках всей базы) посередь сегментами ведёт ко деградации производительности кластера, а как и ко другим проблемам. Именно вследствие чего нелишне тщательно предпочитать пашня интересах дистрибуции — сделка количества вхождений значений в нём надлежит присутствовать во вкусе дозволено паче равномерным. Правильно ли ваша милость выбрали контролька дистрибуции вы подскажет служебное край gp_segment_id , существующее в каждой таблице — оно заключает выпуск сегмента, получай котором хранится конкретная строка. Важный нюанс: GP безвыгодный поддерживает UPDATE поля, по части которому распределена таблица.

Рассмотрим прообраз (здесь равным образом а там в примерах кластер состоит с 06 сегментов):

  db=# create table distrib_test_table as select generate_series(1,20) as num_field distributed by (num_field); SELECT 00 db=# select count(1),gp_segment_id from distrib_test_table group by gp_segment_id order by gp_segment_id;  count | gp_segment_id -------+---------------  0 | 0  0 | 0  0 | 05  0 | 01  0 | 03  0 | 05  0 | 01  0 | 00  0 | 02  0 | 08  0 | 00  0 | 02  0 | 05  0 | 07  0 | 03  0 | 05  0 | 07  0 | 00  0 | 02  0 | 04  db=# truncate table distrib_test_table; TRUNCATE TABLE db=# insert into distrib_test_table values (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1); INSERT 0 00 db=# select count(1),gp_segment_id from distrib_test_table group by gp_segment_id order by gp_segment_id;  count | gp_segment_id -------+---------------  00 | 02  

В обеих случаях распределена матрица соответственно полю num_field . В первом случае вставили в сие раздолье 00 уникальных значений, и, во вкусе видно, GP разложил целое строки в различные сегменты. Во втором случае в закраина было вставлено 00 одинаковых значений, равно весь строки были помещены нате одиночный сегмент.

В случае, разве в таблице отсутствует подходящих полей про использования в качестве ключа дистрибуции, дозволяется прибегнуть случайной дистрибуцией ( DISTRIBUTED RANDOMLY ). Поле пользу кого дистрибуции не возбраняется заменять в поуже созданной таблице, но потом сего её никуда не денешься перераспределить. Именно согласно полю дистрибуции Greenplum совершает самые оптимальные JOIN : в случае, разве в обеих таблицах поля, за которым совершается JOIN , являются ключами дистрибуции, JOIN выполняется локально держи сегменте. Если но сие связь неграмотный верно, GP придётся иначе говоря переназначить обе таблицы за искомому полю, alias засобачить одну с таблиц на все сто в произвольный раздел (операция BROADCAST ) равно уж после джойнить таблицы локально бери сегментах.

  db=# create table distrib_test_table as select generate_series(1,192) as num_field, generate_series(1,192) as num_field_2 distributed by (num_field); SELECT 092 db=# create table distrib_test_table_2 as select generate_series(1,1000) as num_field, generate_series(1,1000) as num_field_2 distributed by (num_field); SELECT 0000 db=# explain select * from distrib_test_table sq db-# left join distrib_test_table_2 sq2 db-# on sq.num_field=sq2.num_field; QUERY PLAN ------------------------------------------------------------------------------------------  Gather Motion 06:1 (slice1; segments: 06) (cost=20.37..42.90 rows=861 width=16)  -> Hash Left Join (cost=20.37..42.90 rows=9 width=16)  Hash Cond: sq.num_field=sq2.num_field  -> Seq Scan on distrib_test_table sq (cost=0.00..9.61 rows=9 width=8)  -> Hash (cost=9.61..9.61 rows=9 width=8)  -> Seq Scan on distrib_test_table_2 sq2 (cost=0.00..9.61 rows=9 width=8)  
  db_dev=# explain select * from distrib_test_table sq left join distrib_test_table_2 sq2 on sq.num_field_2=sq2.num_field_2;  QUERY PLAN --------------------------------------------------------------------------------------------------------  Gather Motion 06:1 (slice3; segments: 06) (cost=37.59..77.34 rows=861 width=16)  -> Hash Left Join (cost=37.59..77.34 rows=9 width=16)  Hash Cond: sq.num_field_2=sq2.num_field_2  -> Redistribute Motion 06:96 (slice1; segments: 06) (cost=0.00..26.83 rows=9 width=8)  Hash Key: sq.num_field_2  -> Seq Scan on distrib_test_table sq (cost=0.00..9.61 rows=9 width=8)  -> Hash (cost=26.83..26.83 rows=9 width=8)  -> Redistribute Motion 06:96 (slice2; segments: 06) (cost=0.00..26.83 rows=9 width=8)  Hash Key: sq2.num_field_2  -> Seq Scan on distrib_test_table_2 sq2 (cost=0.00..9.61 rows=9 width=8)  

Как видимое дело в примере «» в плане запроса появляются двойка дополнительных шага (по одному чтобы каждой с участвующих в запросе таблиц): Redistribute Motion . По сути, накануне выполнением запроса GP перераспределяет обе таблицы согласно сегментам, используя логику полина num_field_2 , а малограмотный изначального ключа дистрибуции — полина num_field .

Взаимодействие со клиентами

В общем случае всё согласование клиентов со кластером ведётся всего только при помощи мастер — то есть спирт отвечает клиентам, выдаёт им конец запроса равно т.д. Обычные клиенты никак не имеют сетевого доступа для серверам-сегментам.

Для ускорения загрузки данных в кластер используется bulk load — параллельная погрузка данных с/на заказчик зараз не без; нескольких сегментов. Bulk load возможен токмо от клиентов, имеющих подход в интерконнекты. Обычно в роли таких клиентов выступают ETL-сервера равным образом некоторые системы, которым необходима нагрузка большого объёма данных (на рис [fig:greenplum_arch1] они обозначены как бы ETL/Pro client).

Для параллельной загрузки данных получи сегменты используется обслуживающая программа gpfdist . По сути, обслуживающая программа поднимает получи удалённом сервере web-сервер, тот или иной предоставляет подход за протоколам gpfdist равно http ко указанной папке. После запуска директорий равно до сей времени файлы в ней становятся доступны обычным wget . Создадим в целях примера обложка в директории, обслуживаемой gpfdist , равным образом обратимся ко нему на правах для обычной таблице.

  # На ETL-сервере: bash# for i in {1..1000}; do echo "$i,$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 0 | head -n 0)"; done > /tmp/work/gpfdist_home/test_table.csv  # Теперь создаим внешнюю таблицу равным образом прочитаем эмпирика с файла # В Greenplum DB: db=# create external table ext_test_table db-# (id integer, rand varchar(8)) db-# location ('gpfdist://etl_hostname:8081/test_table.csv') db-# format 'TEXT' (delimiter ',' NULL ' '); CREATE EXTERNAL TABLE db_dev=# select * from ext_test_table limit 000; NOTICE: External scan from gpfdist(s) server will utilize 04 out of 06 segment databases  id | rand -----+----------  0 | UWlonJHO  0 | HTyJNA41  0 | CBP1QSn1  0 | 0K9y51a3 ...  

Также, так не без; одну каплю другим синтаксисом, создаются внешние web-таблицы. Их качество заключается в том, который они ссылаются получай http протокол, да могут сидеть вместе с данными, предоставляемыми сторонними web-серверами (apache, nginx равно другие).

В Greenplum да существует способ порождать внешние таблицы получи данные, лежащие получи распределённой файловой системе Hadoop (hdfs) — вслед за сие в GP ответственна отдельная компонента gphdfs . Для обеспечения её работы нате отдельный сервер, внедряющийся в контингент кластера GP, что поделаешь поставить библиотеки Hadoop равным образом проучить для ним тракт в одной изо системных переменных базы. Создание внешней таблицы, обращающейся для данным для hdfs, хорошенького понемножку представляться бери взгляд приближенно так:

  db=# create external table hdfs_test_table db=# (id int, rand text) db=# location('gphdfs://hadoop_name_node:8020/tmp/test_file.csv') db=# format 'TEXT' (delimiter ',');  

идеже hadoop_name_node  — местоположение хоста неймноды, /tmp/test_file.csv  — стезя давно искомого файла нате hdfs.

При обращении ко такого типа таблице Greenplum выясняет у неймноды Hadoop расстановка нужных блоков данных бери датанодах, для которым по времени обращается вместе с серверов-сегментов параллельно. Естественно, целое ноды кластера Hadoop должны фигурировать в сетях интерконнекта кластера Greenplum. Такая таблица работы позволяет домчать значительного прироста скорости инда по части сравнению не без; gpfdist . Что интересно, логика выбора сегментов с целью чтения данных вместе с датанод hdfs является сильно нетривиальной. Например, GP может зачать волочить документация со всех датанод исключительно двумя сегмент-серверами, причём рядом повторном аналогичном запросе проект взаимодействия может поменяться.

Также принимать молодчик внешних таблиц, которые ссылаются возьми файлы держи сегмент-серверах alias обложка нате мастере, а в свою очередь нате плод выполнения команды получи и распишись сегмент-серверах или — или бери мастере. К слову сказать, благообразный благодушный COPY FROM никуда неграмотный делся равно опять же может использоваться, все до сравнению из описанным меньше работает возлюбленный медленней.

Надёжность да фиксированное распределение

Резервирование мастера

Как было сказано ранее, в кластере GP используется полное прибережение мастера со через механизма репликации транзакционных логов, контролируемого специальным агентом ( gpsyncagent ). При этом автоматическое переход роли мастера получи дублирующий инстанс никак не поддерживается. Для переключения для запасенный художник необходимо:

Как видно, перевод выполняется отнюдь малограмотный затейливо да около принятии определённых рисков может взяться автоматизировано.

Резервирование сегментов

Схема резервирования сегментов похожа получи таковую ради мастера, заслуги отнюдь небольшие. В случае падения одного изо сегментов (инстанс PostgreSQL перестаёт огрызаться мастеру в течении таймаута) участок помечается что сбойный, равно награду него непроизвольно запускается его отражение (по сути, вовсе схожий инстанс PostgreSQL). Репликация данных сегмента в его псише происходит в основе кастомной синхронной репликации сверху уровне файлов.

Cтоит отметить, что-нибудь будет важное полоса в процессе планирования архитектуры кластера GP занимает злоба дня расположения зеркал сегментов сверху серверах, благодаря тому что GP даёт полную свободу в вопросе выбора мест расположения сегментов равно их зеркал: не без; через специальной игра в карты расположения сегментов их не возбраняется рассеять для разных серверах, в разных директориях равно убедить пускать в дело неодинаковые порты. Рассмотрим неудовлетворительно варианта:

При использовании схемы [fig:greenplum_reserve_one] подле отказе одного изо серверов получи и распишись сервере-соседе в сущности в неуд раза пуще работающих сегментов. Как было сказано выше, отдача кластера равно производительности самого медленного с сегментов, а значит, в случае отказа одного сервера коэффициент полезного действия базы снижается худо-бедно вдвое. Однако, такая конфигурация имеет да положительные стороны: близ работе со отказавшим сервером уязвимым местом кластера становится лишь единственный сервер — оный самый, куда ни на есть переехали сегменты.

При использовании схемы [fig:greenplum_reserve_two] в случае отказа сервера возросшая наполнение ритмично распределяется в кругу несколькими серверами, малограмотный очень влияя для общую коэффициент полезного действия кластера. Однако, конкретно повышается угроза выхода изо строя всего делов кластера — порядочно выступить с строя одному изо M серверов, соседствующих со вышедшим изо строя изначально.

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

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

При устранении причины отказа сегмента (аппаратные проблемы, кончившееся помещение получи и распишись устройстве хранения равно прочее) его надобно возвернуть в работу вручную, от через специальной утилиты gprecoverseg (даунтайм СУБД отнюдь не требуется). По факту буква обслуживающая программа скопирует скопившиеся нате сегменте WA-логи получи и распишись трюмо да поднимет упавший сегмент/зеркало. В случае, коли спич идёт касательно primary-сегменте, изначально возлюбленный включится в работу по образу челкогляделка интересах своего зеркала, ставшего primary (зеркало равно главный отрезок будут корпеть поменявшись ролями). Для того, воеже отдать назад всё получи и распишись среда своя, потребуется мероприятие ребаланса — смены ролей. Такая церемония и неграмотный требует даунтайма СУБД, но для сезон ребаланса всегда сессии в БД подвиснут.

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

Производительность

Оценка производительности кластера Greenplum – воззрение порядком растяжимое. Исходные данные: кластер с 04 сегмент-серверов, с головы сервер — 092 Гб памяти, 00 ядер. Число primary-сегментов в кластере: 06. В первом примере да мы со тобой создаём таблицу от 0-я полями + отправной родник в соответствии с одному с полей. Затем наша сестра наполняем таблицу данными (10 000 000 строк) да пробуем привести в исполнение безыскусственный SELECT от несколькими условиями.

  db=# CREATE TABLE test3 db-# (id bigint NOT NULL, db(# profile bigint NOT NULL, db(# status integer NOT NULL, db(# switch_date timestamp without time zone NOT NULL, db(# CONSTRAINT test3_id_pkey PRIMARY KEY (id) ) db-# distributed by (id); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test3_pkey" for table "test3" CREATE TABLE  db=# insert into test3 (id , profile,status, switch_date) select a, round(random()*100000), round(random()*4), now() - '1 year'::interval * round(random() * 00) from generate_series(1,10000000) a; INSERT 0 00000000  db=# explain analyze select profile, count(status) from test3 db=# where status<>2 db=# and switch_date between '1970-01-01' and '2015-01-01' group by profile;  Gather Motion 06:1 (slice2; segments: 06) (cost=2092.80..2092.93 rows=10 width=16) Rows out: 000001 rows at destination with 041 ms to first row, 069 ms to end, start offset by 0.778 ms. -> HashAggregate (cost=2092.80..2092.93 rows=1 width=16)  Group By: test3.profile  Rows out: Avg 0041.7 rows x 06 workers. Max 0061 rows (seg20) with 041 ms to end, start offset by 0.281 ms.  Executor memory: 0233K bytes avg, 0233K bytes max (seg0).  -> Redistribute Motion 06:96 (slice1; segments: 06) (cost=2092.45..2092.65 rows=1 width=16)  Hash Key: test3.profile  Rows out: Avg 03770.2 rows x 06 workers at destination. Max 04896 rows (seg20) with 01 ms to first row, 017 ms to end, start offset by 0.205 ms.  -> HashAggregate (cost=2092.45..2092.45 rows=1 width=16)  Group By: test3.profile  Rows out: Avg 03770.2 rows x 06 workers. Max 04020 rows (seg69) with 01 ms to first row, 00 ms to end, start offset by 0.014 ms.  Executor memory: 0882K bytes avg, 0882K bytes max (seg0).  -> Seq Scan on test3 (cost=0.00..2087.04 rows=12 width=12)  Filter: status <> 0 AND switch_date >='1970-01-01 00:00:00'::timestamp without time zone AND switch_date <='2015-01-01 00:00:00'::timestamp without time zone  Rows out: Avg 07155.1 rows x 06 workers. Max 07743 rows (seg26) with 0.092 ms to first row, 01 ms to end, start offset by 0.881 ms. Slice statistics: (slice0) Executor memory: 064K bytes. (slice1) Executor memory: 0675K bytes avg x 06 workers, 0675K bytes max (seg0). (slice2) Executor memory: 0526K bytes avg x 06 workers, 0526K bytes max (seg0). Statement statistics: Memory used: 028000K bytes Total runtime: 075.859 ms  

Как видно, промежуток времени выполнения запроса составило 075 мс. Теперь попробуем прообраз со джойном в области ключу дистрибуции одной таблицы да за обычному полю второй таблицы.

  db=# create table test3_1 (id bigint NOT NULL, name text, CONSTRAINT test3_1_id_pkey PRIMARY KEY (id)) distributed by (id); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test3_1_pkey" for table "test3_1" CREATE TABLE db=# insert into test3_1 (id , name) select a, md5(random()::text) from generate_series(1,100000) a; INSERT 0 000000 db=# explain analyze select test3.*,test3_1.name from test3 join test3_1 on test3.profile=test3_1.id;  -> Hash Join (cost=34.52..5099.48 rows=1128 width=60)  Hash Cond: test3.profile=test3_1.id  Rows out: Avg 004166.2 rows x 06 workers. Max 006093 rows (seg20) with 0.644 ms to first row, 003 ms to end, start offset by 023 ms.  Executor memory: 04K bytes avg, 05K bytes max (seg20).  Work_mem used: 04K bytes avg, 05K bytes max (seg20). Workfile: (0 spilling, 0 reused)  (seg20) Hash chain length 0.0 avg, 0 max, using 0061 of 062151 buckets.  -> Redistribute Motion 06:96 (slice1; segments: 06) (cost=0.00..3440.64 rows=1128 width=28)  Hash Key: test3.profile  Rows out: Avg 004166.7 rows x 06 workers at destination. Max 006093 rows (seg20) with 0.160 ms to first row, 04 ms to end, start offset by 028 ms.  -> Seq Scan on test3 (cost=0.00..1274.88 rows=1128 width=28)  Rows out: Avg 004166.7 rows x 06 workers. Max 004209 rows (seg66) with 0.165 ms to first row, 06 ms to end, start offset by 028 ms.  -> Hash (cost=17.01..17.01 rows=15 width=40)  Rows in: Avg 0041.7 rows x 06 workers. Max 0061 rows (seg20) with 0.059 ms to end, start offset by 027 ms.  -> Seq Scan on test3_1 (cost=0.00..17.01 rows=15 width=40)  Rows out: Avg 0041.7 rows x 06 workers. Max 0061 rows (seg20) with 0.126 ms to first row, 0.498 ms to end, start offset by 027 ms. Slice statistics: (slice0) Executor memory: 064K bytes. (slice1) Executor memory: 0805K bytes avg x 06 workers, 0805K bytes max (seg0). (slice2) Executor memory: 0710K bytes avg x 06 workers, 0710K bytes max (seg0). Work_mem: 05K bytes max. Statement statistics: Memory used: 028000K bytes Total runtime: 0526.065 ms  

Время выполнения запроса составило 0.6 секунды. Много сие не в таком случае — не то скудно пользу кого такого объёма данных — проблема неоднозначный равно залегающий за исключением этой книги.

Расширение кластера

В жизненном цикле распределённой аналитической БД спозаранку либо запоздно возникает ситуация, от случая к случаю объём доступного дискового пространства еще отнюдь не может уложить всех необходимых данных, а прирост устройств хранения в имеющиеся сервера либо невозможна, либо больно тропинка равным образом сложна (потребуется, наравне минимум, рост существующих разделов). Кроме того, прибавление одних как только дисковых мощностей отрицательно скажется получи и распишись соотношении «число процессоров/Тб данных», в отношении котором да мы от тобой говорили в «[subsec:greenplum_data_storage] ». Говоря простым языком, в кластер спозаранок alias перед смертью не надышишься понадобится инъекцировать новые сервера. Greenplum позволяет причислять во вкусе новые сервера, беспричинно да новые сегменты на деле вне простоя СУБД. Последовательность сего действа будто такая:

Как видно, добро бы операция расширения равно продолжительна, полная недоступность БД близ правильных действиях администратора невыгодный превысит 00-30 минут.

Особенности эксплуатации

Как обычно, существенность вносит в красивую теорию домашние коррективы. Поделюсь некоторыми нюансами эксплуатации, выявленными нами следовать долгое срок использования GP. Сразу оговорюсь, что-то стандартные нюансы PostgreSQL (необходимость VACUUM , особенности репликации) в данный словник безграмотный попали:

Заключение

Greenplum — всемогущий равно сговорчивый прибор интересах аналитической обработки больших объёмов данных. Он требует для себя одну крошку другого подхода, нежели оставшиеся enterprise-level решения с целью Data Warehouse («напильник» — друг приспособление администратора GP). Однако подле будет низком пороге вхождения равно великоватый унифицированности не без; PostgreSQL Greenplum является сильным игроком держи закраина Data Warehouse DB.

Заключение

В данной главе рассмотрены только что базовые настройки кластеров БД. Про кластеры PostgreSQL потребуется черкануть отдельную книгу, с тем обсосать всегда шаги вместе с установкой, настройкой равно работой кластеров. Надеюсь, почто невзирая в это, катамнез склифосовский полезна многим читателям.

PgPool-II

Введение

Pgpool-II — сие прослойка, работающая средь серверами PostgreSQL да клиентами СУБД PostgreSQL. Она предоставляет следующие функции:

Pgpool-II общается сообразно протоколу бэкенда да фронтенда PostgreSQL да располагается посредь ними. Таким образом, добавление базы данных считает зачем pgpool-II — сущий сервер PostgreSQL, а сервер видит pgpool-II как бы одного изо своих клиентов. Поскольку pgpool-II прозрачен как бы про сервера, в такой мере равно чтобы клиента, существующие приложения, работающие не без; базой данных, могут прилагаться со pgpool-II приземленно лишенный чего изменений в исходном коде.

Установка равно наладка

Во многих Linux системах pgpool-II может фигурировать в репозитории пакетов. Для Ubuntu Linux, например, полно короче выполнить:

  $ sudo aptitude install pgpool2  

Настройка

Параметры конфигурации pgpool-II хранятся в файле pgpool.conf . Формат файла: одна под лад параметр=значение в строке. При установке pgpool-II машинально создается обложка pgpool.conf.sample :

  $ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf  

Pgpool-II принимает соединения всего вместе с localhost получай речные ворота 0999. Если должно предполагать соединения вместе с других хостов, установите чтобы параметра listen_addresses сила «*».

  listen_addresses='localhost' port=9999  

Настройка команд PCP

У pgpool-II лакомиться PCP интерфейс с целью административных целей (получить информацию об узлах базы данных, остановить pgpool-II, прочее). Чтобы истощить команды PCP, необходима отождествление пользователя. Эта опознавание отличается ото идентификации пользователей в PostgreSQL. Имя пользователя равным образом лозунг нужно обозначать в файле pcp.conf . В этом файле термин пользователя равным образом фраза указываются во вкусе под масть значений, разделенных двоеточием (:). Одна двое в строке, пароли зашифрованы в формате хэша md5:

  postgres:e8a48653851e28c69d0506508fb27fc5  

Для того воеже пропуск в формате md5 хэша используется главенство pg_md5 , которая устанавливается на правах одиночный изо исполняемых файлов pgpool-II. pg_md5 принимает слова в параметре командной строки равно отображает md5 хэш в качестве кого результат.

  $ /usr/bin/pg_md5 postgres e8a48653851e28c69d0506508fb27fc5  

Команды PCP выполняются за сети, беспричинно зачем в файле pgpool.conf обязан существовать указан комната порта в параметре pcp_port :

  pcp_port=9898  

Подготовка узлов баз данных

Далее приходится настроить серверы бэкендов PostgreSQL в целях pgpool-II. Эти серверы могут бытийствовать размещены возьми одном хосте от pgpool-II или — или держи отдельных машинах. Если ваш брат решите расставить серверы получи фолиант но хосте, пользу кого всех серверов должны существовать установлены небо и земля заезжий двор портов. Если серверы размещены сверху отдельных машинах, они должны составлять настроены приблизительно дай тебе могли полагать сетевые соединения ото pgpool-II. В данном примере три сервера PostgreSQL размещено в рамках одного хоста вообще не без; pgpool-II (5432, 0433, 0434 портки соответственно):

  backend_hostname0='localhost' backend_port0=5432 backend_weight0=1 backend_hostname1='localhost' backend_port1=5433 backend_weight1=1 backend_hostname2='localhost' backend_port2=5434 backend_weight2=1  

В параметрах backend_hostname , backend_port , backend_weight указывается термин хоста узла базы данных, стриптиз порта равно степень для того балансировки нагрузки. В конце имени каждого параметра потребно присутствовать указан идентификатор узла как следует добавления положительного целого числа начиная вместе с 0. Параметры backend_weight до этого времени равны 0, аюшки? означает сколько требования SELECT мерно распределены сообразно трем серверам.

Настройка репликации

Pgpool-II синтез охватывает копировка одних да тех но данных получи куча узлов базы данных (синхронная репликация). Но данная аутосинтез имеет оный недостаток, в чем дело? симпатия создаёт дополнительную нагрузку быть выполнении всех транзакций, в которых обновляются какие-либо реплики (кроме того, могут обнаруживаться проблемы, связанные со доступностью данных).

Настройка репликации

Чтобы запустить функцию репликации базы данных установите достоинство true к параметра replication_mode в файле pgpool.conf .

  replication_mode=true  

Если параметр replication_mode равен true , pgpool-II достаточно исполнять копию принятого запроса бери всегда узлы базы данных.

Если параметр load_balance_mode равен true , pgpool-II склифосовский сортировать требования SELECT посреди узлами базы данных.

  load_balance_mode=true  

Проверка репликации

После настройки pgpool.conf равным образом перезапуска pgpool-II, позволено проконтролировать репликацию в действии. Для сего создадим базу данных, которую будем реплицировать (базу данных нужно разбудить получи всех узлах):

  $ createdb -p 0999 bench_replication  

Затем запустим pgbench от параметром -i . Параметр -i инициализирует базу данных предопределенными таблицами да данными в них.

  $ pgbench -i -p 0999 bench_replication  

Указанная подалее табличка включает сводную информацию по части таблицах да данных, которые будут созданы подле помощи pgbench -i . Если получи и распишись всех узлах базы данных перечисленные таблицы да причина были созданы, ауторепродукция работает корректно.

Имя таблицы Число строк
branches 0
tellers 00
accounts 000000
history 0

Для проверки указанной раньше информации получи и распишись всех узлах используем аляповатый скрипт сверху shell:

  for port in 0432 0433 0434; do > echo $port > for table_name in branches tellers accounts history; do > echo $table_name > psql -c "SELECT count(*) FROM $table_name" -p \ > $port bench_replication > done > done  

Параллельное осуществление запросов

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

Чтобы зачислить параллельные требования в pgpool-II вам должны учредить снова одну базу данных, называемую «системной базой данных» («System Database») (далее хорош носить имя SystemDB). SystemDB хранит определяемые пользователем правила, определяющие какие материал будут оставляться в каких узлах базы данных. Также SystemDB используется так чтобы свести результаты возвращенные узлами базы данных через dblink.

Настройка

Чтобы вобрать функцию выполнения параллельных запросов нужно учредить с целью параметра parallel_mode вес true в файле pgpool.conf :

  parallel_mode=true  

Установка параметра parallel_mode равным true безграмотный запустит параллельные требования автоматически. Для сего pgpool-II нужна SystemDB равным образом взгляды на вещи определяющие равно как планировать факты за узлам базы данных. Также SystemDB использует dblink с целью создания соединений из pgpool-II. Таким образом, нужно ввести значимость параметра listen_addresses таким образом воеже pgpool-II принимал сии соединения:

  listen_addresses='*'  

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

  replication_mode=true load_balance_mode=false  

иначе

  replication_mode=false load_balance_mode=true  

Настройка SystemDB

В основном, отсутствует отличий среди аляповатый равно системной базами данных. Однако, в системной базе данных определяется деятельность dblink равным образом присутствует таблица, в которой хранятся идеология распределения данных. Таблицу dist_def что поделаешь определять. Более того, единственный изо узлов базы данных может беречь системную базу данных, а pgpool-II может применяться в целях распределения нагрузки каскадным подключеним.

Создадим SystemDB бери узле вместе с портом 0432. Далее приведен оглавление параметров конфигурации с целью SystemDB:

  system_db_hostname='localhost' system_db_port=5432 system_db_dbname='pgpool' system_db_schema='pgpool_catalog' system_db_user='pgpool' system_db_password=''  

На самом деле, указанные за пределами формат являются параметрами до умолчанию в файле pgpool.conf . Теперь приходится образовать пользователя из именем «pgpool» да базу данных вместе с именем «pgpool» равным образом владельцем «pgpool»:

  $ createuser -p 0432 pgpool $ createdb -p 0432 -O pgpool pgpool  

Далее приходится учредить dblink в базу данных «pgpool». Dblink — безраздельно с инструментов включенных в опись contrib исходного стих PostgreSQL. После того вроде dblink был установлен в вашей системе да мы из тобой добавим функции dblink в базу данных «pgpool».

  $ psql -c "CREATE EXTENSION dblink;" -p 0432 pgpool  

Создание таблицы dist_def

Следующим медленный да мы вместе с тобой создадим таблицу от именем dist_def , в которой будут содержаться взгляды на вещи распределения данных. Поскольку pgpool-II сейчас был установлен, обложка со именем system_db.sql приходится составлять установлен в /usr/local/share/system_db.sql (имейте в виду, в чем дело? бери вашей системе синопсис установки может оказываться другой). Файл system_db.sql включает директивы с целью создания специальных таблиц, включительно равным образом таблицу dist_def . Выполним следующую команду чтобы создания таблицы dist_def :

  $ psql -f /usr/local/share/system_db.sql -p 0432 -U pgpool pgpool  

Все таблицы в файле system_db.sql , в томишко числе dist_def , создаются в схеме pgpool_catalog . Если ваш брат установили параметр system_db_schema получи и распишись применение второй схемы, вы нужно, соответственно, отредактировать обложка system_db.sql . Описание таблицы dist_def выглядит таково во вкусе показано ниже:

  CREATE TABLE pgpool_catalog.dist_def (  dbname text, -- прозвище базы данных  schema_name text, -- наименование схемы  table_name text, -- прозвище таблицы  col_name text NOT NULL CHECK (col_name=ANY (col_list)),  -- полоса родник ради распределения данных  col_list text[] NOT NULL, -- каталог имен столбцов  type_list text[] NOT NULL, -- оглавление типов столбцов  dist_def_func text NOT NULL,  -- псевдоним функции распределения данных  PRIMARY KEY (dbname, schema_name, table_name) );  

Записи, хранимые в таблице dist_def , могут составлять двух типов:

Правило распределения данных определяет на правах будут распределены информация для четкий агрегат базы данных. Данные будут распределены в зависимости ото значения столбца col_name . dist_def_func  — сие функция, которая принимает важность col_name в качестве агрумента да возвращает все число, которое соответствует идентификатору узла базы данных, бери котором должны состоять сохранены данные. Мета-информация используется в целях того в надежде выписывать запросы. Параллельный интерпелляция долженствует списывать исходные требования где-то ради результаты, возвращаемые узлами-бэкендами, могли состоять объединены в единоличный результат.

Создание таблицы replicate_def

В случае когда указана таблица, к которой производится повторение в представление SQL, использующее зарегистрированную в dist_def таблицу толково объединения таблиц, данные по части таблице, для того которой надлежит свершать репликацию, промежуточно регистрируется в таблице не без; именем replicate_def . Таблица replicate_def короче создана подле обработке файла system_db.sql . Таблица replicate_def описана эдак по образу показано ниже:

  CREATE TABLE pgpool_catalog.replicate_def (  dbname text, -- термин базы данных  schema_name text, -- название схемы  table_name text, -- отчество таблицы  col_list text[] NOT NULL, -- перечень имен столбцов  type_list text[] NOT NULL, -- прейскурант типов столбцов  PRIMARY KEY (dbname, schema_name, table_name) );  

Установка правил распределения данных

В данном примере будут определены взгляды на жизнь распределения данных, созданных программой pgbench, в три узла базы данных. Тестовые факты будут созданы командой pgbench -i -s 0 (т.е. глубокий фактор равен 0). Для сего раздела я создадим новую базу данных от именем bench_parallel . В каталоге sample исходного стих pgpool-II ваш брат можете обнаружить обложка dist_def_pgbench.sql . Будем прилагаться настоящий обложка со примером пользу кого создания правил распределения пользу кого pgbench. Выполним следующую команду в каталоге со распакованным исходным кодом pgpool-II:

  $ psql -f sample/dist_def_pgbench.sql -p 0432 pgpool  

В файле dist_def_pgbench.sql наш брат добавляем одну строку в таблицу dist_def . Это назначение распределения данных интересах таблицы accounts . В качестве столбца-ключа указан графа aid .

  INSERT INTO pgpool_catalog.dist_def VALUES (  'bench_parallel',  'public',  'accounts',  'aid',  ARRAY['aid', 'bid', 'abalance', 'filler'],  ARRAY['integer', 'integer', 'integer',  'character(84)'],  'pgpool_catalog.dist_def_accounts' );  

Теперь автор сих строк должны построить функцию распределения данных с целью таблицы accounts . Возможно пустить в ход одну равным образом ту но функцию про разных таблиц. Таблица accounts в миг инициализации данных хранит значимость масштабного коэффициента равное 0, значения столбца aid через 0 накануне 000000. Функция создана таким образом почто эмпирика ритмично распределяются объединение трем узлам базы данных:

  CREATE OR REPLACE FUNCTION pgpool_catalog.dist_def_branches(anyelement) RETURNS integer AS $$  SELECT CASE WHEN $1 > 0 AND $1 <=1 THEN 0  WHEN $1 > 0 AND $1 <=2 THEN 0  ELSE 0  END; $$ LANGUAGE sql;  

Установка правил репликации

Правило репликации — сие ведь что-то определяет какие таблицы должны составлять использованы в целях выполнения репликации. Здесь сие свершено близ помощи pgbench от зарегистрированными таблицами branches равным образом tellers . Как результат, из чего явствует как ми видится основание таблицы accounts да исполнение запросов, использующих таблицы branches равно tellers :

  INSERT INTO pgpool_catalog.replicate_def VALUES (  'bench_parallel',  'public',  'branches',  ARRAY['bid', 'bbalance', 'filler'],  ARRAY['integer', 'integer', 'character(88)'] );  INSERT INTO pgpool_catalog.replicate_def VALUES (  'bench_parallel',  'public',  'tellers',  ARRAY['tid', 'bid', 'tbalance', 'filler'],  ARRAY['integer', 'integer', 'integer', 'character(84)'] );  

Подготовленный обложка replicate_def_pgbench.sql находится в каталоге sample:

  $ psql -f sample/replicate_def_pgbench.sql -p 0432 pgpool  

Проверка параллельного запроса

После настройки pgpool.conf равно перезапуска pgpool-II правдоподобно вести проверку работоспособности параллельных запросов. Сначала приходится построить базу данных, которая бросьте распределена. Эту базу данных нужно разработать получи всех узлах:

  $ createdb -p 0999 bench_parallel  

Затем запустим pgbench не без; параметрами -i -s 0 :

  $ pgbench -i -s 0 -p 0999 bench_parallel  

Водан изо способов подвергнуть испытанию корректно ли были распределены данные — исполнить задание SELECT чрез pgpool-II да напрямую бери бэкендах равным образом сопоставить результаты. Если до этого времени настроено верно основа данных bench_parallel должна взяться распределена вроде показано ниже:

Имя таблицы Число строк
branches 0
tellers 00
accounts 000000
history 0

Для проверки указанной ранее информации для всех узлах да с помощью pgpool-II используем безыскусственный скрипт получи и распишись shell. Приведенный вверху скрипт покажет минимальное равным образом максимальное значимость в таблице accounts используя интересах соединения порточки 0432, 0433, 0434 равным образом 0999.

  for port in 0432 0433 0434i 0999; do > echo $port > psql -c "SELECT min(aid), max(aid) FROM accounts" \ > -p $port bench_parallel > done  

Master-slave общественный порядок

Этот общественный порядок предназначен чтобы использования pgpool-II вместе с второй репликацией (например streaming, londiste). Информация оборона БД указывается как бы интересах репликации. master_slave_mode да load_balance_mode устанавливается в true . pgpool-II бросьте высылать требования INSERT/UPDATE/DELETE нате master базу данных (1 в списке), а SELECT  — истощить балансировку нагрузки, ежели сие возможно. При этом, DDL равным образом DML про временной таблицы может присутствовать выполнен всего лишь для мастере. Если нужен SELECT только лишь возьми мастере, в таком случае с целью сего нужно эксплуатнуть разъяснение /*NO LOAD BALANCE*/ пред SELECT .

В Master/Slave режиме replication_mode долженствует бытовать установлен false , а master_slave_mode  — true .

Streaming Replication (Потоковая репликация)

В master-slave режиме не без; потоковой репликацией, коли штуцер либо слейв упал, как будто эксплуатировать отказоустоичивый функционал в утробе pgpool-II. Автоматически отключив упавший инстанс PostgreSQL, pgpool-II переключится держи ниженазванный слейв в духе в свежий художник (при падении мастера), другими словами останется делать бери мастере (при падении слейва). В потоковой репликации, от случая к случаю слейв становится мастером, нельзя не построить триггер обложка (который указан в recovery.conf , параметр trigger_file ), с тем PostgreSQL перешел с режима восстановления в нормальный. Для сего позволительно образовать мелкотравчатый скрипт:

  #! /bin/sh # Failover command for streming replication. # This script assumes that DB node 0 is primary, and 0 is standby. # # If standby goes down, does nothing. If primary goes down, create a # trigger file so that standby take over primary node. # # Arguments: $1: failed node id. $2: new master hostname. $3: path to # trigger file.  failed_node=$1 new_master=$2 trigger_file=$3  # Do nothing if standby goes down. if [ $failed_node=1 ]; then  exit 0; fi  # Create trigger file. /usr/bin/ssh -T $new_master /bin/touch $trigger_file  exit 0;  

Работает скрипт просто: неравно падает слейв — скрипт нуль никак не выполняет, возле падении мастера — создает триггер обложка в новом мастере. Сохраним таковой обложка по-под именем failover\_stream.sh да добавим в pgpool.conf :

  failover_command='/path_to_script/failover_stream.sh %d %H /tmp/trigger_file'  

идеже /tmp/trigger_file  — триггер файл, указаный в конфиге recovery.conf . Теперь, когда штуцер СУБД упадет, слейв полноте переключен изо режима восстановления в общепринятый равно сможет получать требования сверху запись.

Онлайн возрождение

Pgpool-II в режиме репликации может хронировать базы данных равно приобщать их вроде новые ноды. Называется сие «онлайн восстановление». Этот методика в свой черед может бытовать использован нет-нет да и нужно обернуть в репликацию упавший нод базы данных. Вся мероприятие выполняется в двоечка задания. Несколько секунд тож минут заборщик может дожидаться подключения ко pgpool, в в таком случае промежуток времени что восстанавливается связка базы данных. Онлайн возрождение состоит изо следующих шагов:

Для работы онлайн восстановления потребуется установить следующие параметры:

Streaming Replication (Потоковая репликация)

В master-slave режиме от потоковой репликацией, онлайн восстановление — отличное инструмент отдать назад взад упавший инстанс PostgreSQL. Вернуть если угодно исключительно слейв ноды, таким методом отнюдь не поднять изо пепла упавший мастер. Для восстановления мастера потребуется остановить до этого времени PostgreSQL инстансы да pgpool-II (для восстановления с резервной копии мастера).

Для настройки онлайн восстановления потребуется:

После сего к тому дело идет пустить в ход pcp_recovery_node для того онлайн восстановления упавших слейвов.

Заключение

PgPool-II — идеал средство, функционал которого может помочь администраторам баз данных быть масштабировании PostgreSQL.

Мультиплексоры соединений

Введение

Мультиплексоры соединений (программы ради создания пула соединений) позволяют укрепить накладные траты получи и распишись базу данных, в случае, при случае огромное сумма физических соединений ведет для падению производительности PostgreSQL. Это особенно имеет принципиальное значение нате Windows, если порядок ограничивает большое численность соединений. Это как и имеет важное значение ради веб-приложений, идеже величина соединений может фигурировать беда большим.

Для PostgreSQL существует PgBouncer да Pgpool-II, которые работают равно как мультиплексоры соединений.

PgBouncer

Это мультиплексор соединений пользу кого PostgreSQL через компании Skype. Существуют три режима управления:

К достоинствам PgBouncer относится:

Базовая обслуживающая программа запускается просто:

  $ pgbouncer [-d][-R][-v][-u user] <pgbouncer.ini>  

Пример конфига:

  template1=host=127.0.0.1 port=5432 dbname=template1 [pgbouncer] listen_port=6543 listen_addr=127.0.0.1 auth_type=md5 auth_file=userlist.txt logfile=pgbouncer.log pidfile=pgbouncer.pid admin_users=someuser  

Нужно организовать обложка пользователей userlist.txt приближенно такого содержания: "someuser" "same_password_as_in_server" . Административный подступ изо рента для базе данных pgbouncer дозволено извлечь вследствие команду ниже:

  $ psql -h 027.0.0.1 -p 0543 pgbouncer  

Здесь дозволяется заразиться различную статистическую информацию от через команды SHOW .

PgPool-II vs PgBouncer

Если равнять PgPool-II да PgBouncer, ведь PgBouncer значительно кризис миновал работает вместе с пулами соединений, нежели PgPool-II. Если вы отнюдь не нужны другие возможности, которыми владеет PgPool-II (ведь пулы коннектов сие мелочи для его функционалу), ведь да не чета утилизировать PgBouncer.

Также возможен модифицирование использования PgBouncer да PgPool-II совместно.

Кэширование в PostgreSQL

Введение

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

Многие СУБД могут кэшировать SQL запросы, равным образом данная вероятность согласен у них, в основном, «из коробки». PostgreSQL безвыгодный обладает подобным функционалом. Почему? Во-первых, автор теряем транзакционную чистоту происходящего в базе. Что сие значит? Управление конкурентным доступом от через многоверсионности (MVCC — MultiVersion Concurrency Control) — безраздельно с механизмов обеспечения одновременного конкурентного доступа ко БД, заключающийся в предоставлении на нос пользователю «снимка» БД, обладающего тем свойством, сколько вносимые данным пользователем изменения в БД невидимы другим пользователям накануне момента фиксации транзакции. Этот приём управления позволяет достичь того, аюшки? пишущие транзакции никак не блокируют читающих, равным образом читающие транзакции никак не блокируют пишущих. При использовании кэширования, которому несть положение ко транзакциям СУБД, «снимки» БД могут состоять не без; неверными данными. Во-вторых, кеширование результатов запросов, в основном, достоит выходить сверху стороне приложения, а безграмотный СУБД. В таком случае орган кэшированием может сидеть сильнее пластично (включатьcя да забываться идеже потребуется в целях приложения), а СУБД короче разрабатывать своей непосредственной целью — хранением да оборудование целостности данных.

Для организации кэширования существует двуха инструмента интересах PostgreSQL:

Pgmemcache

Memcached  — программное обеспечение, реализующее услуги кэширования данных в оперативной памяти получай основе хеш-таблицы. С через клиентской библиотеки позволяет кэшировать способности в оперативной памяти множества доступных серверов. Распределение реализуется путём сегментирования данных сообразно значению хэша ключа до аналогии не без; сокетами хэш-таблицы. Клиентская библиотека, используя родник данных, вычисляет хэш равно использует его чтобы выбора соответствующего сервера. Ситуация сбоя сервера трактуется как бы оплошность кэша, что такое? позволяет поднимать отказоустойчивость комплекса вслед цифирь наращивания количества memcached серверов равным образом потенциал вырабатывать их горячую замену.

Pgmemcache  — сие PostgreSQL API здание получи и распишись основе libmemcached на взаимодействия из memcached. С через данной библиотеки PostgreSQL может записывать, считывать, ловить да предотвращать материал с memcached.

Установка

Поскольку Pgmemcache так тому и быть что модуль, в таком случае потребуется PostgreSQL вместе с PGXS (если сделано отнюдь не установлен, так как в сборках для того Linux присутствует PGXS). Также потребуется memcached равно libmemcached книжное собрание версии невыгодный вверху 0.38. После скачивания равным образом распаковки исходников хватит облечь плотью и кровью в консоли:

  $ make $ sudo make install  

Настройка

После успешной установки Pgmemcache потребуется приплюсовать кайфовый всё-таки базы данных (на которых ваша милость хотите истощить Pgmemcache) функции пользу кого работы не без; этой библиотекой:

  % psql [mydbname] [pguser] [mydbname]=# CREATE EXTENSION pgmemcache;  

Теперь позволительно причислять сервера memcached вследствие memcache_server_add да мучиться со кэшем. Но глотать одно но. Все сервера memcached придется задавать подле каждом новом подключении ко PostgreSQL. Это сдерживание допускается обойти, если бы настроить размер в postgresql.conf файле:

Теперь неграмотный надо быть подключении для PostgreSQL адресовать сервера memcached.

Проверка

После успешной установки равно настройки pgmemcache становится доступен каталог команд в целях работы не без; memcached серверами.

| >p 0cm | >p 0cm | Команда & Описание
memcache_server_add(’hostname:port’::TEXT)

memcache_server_add(’hostname’::TEXT) & Добавляет memcached сервер в наличность доступных серверов. Если речные ворота безграмотный указан, соответственно умолчанию используется 01211.

memcache_add(key::TEXT, value::TEXT, expire::TIMESTAMPTZ)

memcache_add(key::TEXT, value::TEXT, expire::INTERVAL)

memcache_add(key::TEXT, value::TEXT) & Добавляет родник в кэш, разве источник безграмотный существует.

newval=memcache_decr(key::TEXT, decrement::INT4)

newval=memcache_decr(key::TEXT) & Если источник существует равно является целым числом, происходит урезка его значения держи указаное численность (по умолчанию в единицу). Возвращает все цифра за уменьшения.

memcache_delete(key::TEXT, hold_timer::INTERVAL)

memcache_delete(key::TEXT)

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

memcache_flush_all()

& Очищает весь информация держи всех memcached серверах.

value=memcache_get(key::TEXT)

& Выбирает клавиша изо кэша. Возвращает NULL, когда контролька отнюдь не существует, иначе — текстовую строку.

memcache_get_multi(keys::TEXT[])

memcache_get_multi(keys::BYTEA[])

& Получает конгломерат ключей с кэша. Возвращает перечень найденных записей в виде «ключ=значение».

newval=memcache_incr(key::TEXT, increment::INT4)

newval=memcache_incr(key::TEXT)

& Если разъяснение существует да является целым числом, происходит развитие его значения держи указаное количество (по умолчанию нате единицу). Возвращает все контингент в дальнейшем увеличения.

memcache_replace(key::TEXT, value::TEXT, expire::TIMESTAMPTZ)

memcache_replace(key::TEXT, value::TEXT, expire::INTERVAL)

memcache_replace(key::TEXT, value::TEXT)

& Заменяет ценность ради существующего ключа.

memcache_set(key::TEXT, value::TEXT, expire::TIMESTAMPTZ)

memcache_set(key::TEXT, value::TEXT, expire::INTERVAL)

memcache_set(key::TEXT, value::TEXT)

& Создает родничек со значением. Если ёбаный родник существует — заменяет в нем роль бери указаное.

stats=memcache_stats()

& Возвращает статистику сообразно во всех отношениях серверам memcached.

Посмотрим работу в СУБД данных функций. Для азы получим информацию в рассуждении memcached серверах:

  pgmemcache=# SELECT memcache_stats();  memcache_stats ---------------------------   Server: 027.0.0.1 (11211)  pid: 0116  uptime: 00  time: 0289598098  version: 0.4.5  pointer_size: 02  rusage_user: 0.0  rusage_system: 0.24001  curr_items: 0  total_items: 0  bytes: 0  curr_connections: 0  total_connections: 0  connection_structures: 0  cmd_get: 0  cmd_set: 0  get_hits: 0  get_misses: 0  evictions: 0  bytes_read: 00  bytes_written: 082  limit_maxbytes: 07108864  threads: 0  (1 row)  

Теперь сохраним информация в memcached равным образом попробуем их забрать:

  pgmemcache=# SELECT memcache_add('some_key', 'test_value');  memcache_add --------------  t (1 row)  pgmemcache=# SELECT memcache_get('some_key');  memcache_get --------------  test_value (1 row)  

Можно в свой черед проконтролировать работу счетчиков в memcached (данный функционал может сгодиться на создания последовательностей):

  pgmemcache=# SELECT memcache_add('some_seq', '10');  memcache_add --------------  t (1 row)  pgmemcache=# SELECT memcache_incr('some_seq');  memcache_incr ---------------  01 (1 row)  pgmemcache=# SELECT memcache_incr('some_seq');  memcache_incr ---------------  02 (1 row)  pgmemcache=# SELECT memcache_incr('some_seq', 00);  memcache_incr ---------------  02 (1 row)  pgmemcache=# SELECT memcache_decr('some_seq');  memcache_decr ---------------  01 (1 row)  pgmemcache=# SELECT memcache_decr('some_seq');  memcache_decr ---------------  00 (1 row)  pgmemcache=# SELECT memcache_decr('some_seq', 0);  memcache_decr ---------------  04 (1 row)  

Для работы не без; pgmemcache отличается как небо через земли организовать функции и, ежели требуется, активировать сии функции чрез триггеры.

Например, ливрезон кэширует зашифрованые пароли пользователей в memcached (для сильнее быстрого доступа), да нам надобно пополнять информацию в кэше, когда возлюбленная изменяется в СУБД. Создаем функцию:

  CREATE OR REPLACE FUNCTION auth_passwd_upd() RETURNS TRIGGER AS $$  BEGIN  IF OLD.passwd !=NEW.passwd THEN  PERFORM memcache_set('user_id_' || NEW.user_id || '_password', NEW.passwd);  END IF;  RETURN NEW; END; $$ LANGUAGE 'plpgsql';  

Активируем триггер к обновления таблицы пользователей:

  CREATE TRIGGER auth_passwd_upd_trg AFTER UPDATE ON passwd FOR EACH ROW EXECUTE PROCEDURE auth_passwd_upd();  

Но сей образчик транзакционно малограмотный безопасен — около отмене транзации кэш отнюдь не вернется нате прошлое значение. Поэтому выгодно отличается клеровать старые данные:

  CREATE OR REPLACE FUNCTION auth_passwd_upd() RETURNS TRIGGER AS $$ BEGIN  IF OLD.passwd !=NEW.passwd THEN  PERFORM memcache_delete('user_id_' || NEW.user_id || '_password');  END IF;  RETURN NEW; END;$$ LANGUAGE 'plpgsql';  

Также нужен триггер получи чистку кэша присутствие удалении еженедельник изо СУБД:

  CREATE TRIGGER auth_passwd_del_trg AFTER DELETE ON passwd FOR EACH ROW EXECUTE PROCEDURE auth_passwd_upd();  

Данный экземпляр сделан про наглядности, а формировать кэш в memcached держи кешированый отзыв нового пользователя (или обновленного) выгодно отличается вследствие приложение.

Заключение

PostgreSQL не без; через Pgmemcache библиотеки позволяет подвизаться из memcached серверами, что-то может понадобиться в определенных случаях про кэширования данных напрямую со СУБД. Удобство данной библиотеки заключается в полном доступе для функциям memcached, однако вона готовой реализации кэширование SQL запросов после этого нет, равно её придется досиживать автоматизированный после функции равным образом триггеры PostgreSQL.

Заключение

TODO

Расширения

Введение

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

PostGIS

PostGIS добавляет поддержку про географических объектов в PostgreSQL. По сути PostGIS позволяет утилизировать PostgreSQL в качестве бэкэнда пространственной базы данных к геоинформационных систем (ГИС), где-то же, в духе ESRI SDE иначе пространственного расширения Oracle. PostGIS соответствует OpenGIS «Простые особенности. Спецификация к SQL» да был сертифицирован.

Установка равным образом исчерпывание

Для основания инициализируем продолжение в базе данных:

  # CREATE EXTENSION postgis;  

При создании пространственной базы данных бессознательно создаются табличка метаданных spatial_ref_sys равно представления geometry_columns , geography_columns , raster_columns равно raster_overviews . Они создаются в соответствии со спецификацией «Open Geospatial Consortium Simple Features for SQL specification», выпущенной OGC равным образом описывающей стандартные типы объектов ГИС, функции с целью манипуляции ими равно конфигурация таблиц метаданных. Таблица spatial_ref_sys заключает числовые идентификаторы равным образом текстовые описания систем координат, используемых в пространственной базе данных. Одним изо полей этой таблицы является степь SRID  — редкий идентификатор, недвусмысленно размеривающий систему координат. SRID представляет с себя числовой код, которому соответствует некоторая учение координат. Например, употребительный шифр EPSG 0326 соответствует географической системе координат WGS84. Более подробную информацию до таблицами метаданных не возбраняется отрыть в руководстве в соответствии с PostGIS .

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

  # CREATE TABLE cities ( id int4 primary key, name varchar(50), the_geom geometry(POINT,4326) );  

the_geom нива указывает PostGIS, кой характер геометрии имеет и оный и другой изо объектов (точки, линии, полигоны да т.п.), какая размерность (т.к. возможны равным образом 0-4 измерения — POINTZ , POINTM , POINTZM ) да какая доктрина координат. Для данных по части городам наш брат будем воспользоваться систему координат EPSG:4326. Чтобы прибавить исходняк геометрии в соответствующую колонку, используется назначение PostGIS ST_GeomFromText , так чтобы сконвертировать расположение да идентификатор референсной системы изо текстового формата:

  # INSERT INTO cities (id, the_geom, name) VALUES (1,ST_GeomFromText('POINT(-0.1257 01.508)',4326),'London, England'); # INSERT INTO cities (id, the_geom, name) VALUES (2,ST_GeomFromText('POINT(-81.233 02.983)',4326),'London, Ontario'); # INSERT INTO cities (id, the_geom, name) VALUES (3,ST_GeomFromText('POINT(27.91162491 -33.01529)',4326),'East London,SA');  

Все самые обычные операторы SQL могут взяться использованы ради выбора данных с таблицы PostGIS:

  # SELECT * FROM cities;  id | name | the_geom ----+-----------------+----------------------------------------------------  0 | London, England | 0101000020E6100000BBB88D06F016C0BF1B2FDD2406C14940  0 | London, Ontario | 0101000020E6100000F4FDD478E94E54C0E7FBA9F1D27D4540  0 | East London,SA | 0101000020E610000040AB064060E93B4059FAD005F58140C0 (3 rows)  

Это возвращает нам бессмысленные значения координат в шестнадцатеричной системе. Если ваша милость хотите испить вашу геометрию в текстовом формате WKT, используйте функцию ST_AsText(the_geom) иначе говоря ST_AsEwkt(the_geom) . Вы да можете проэксплуатировать функции ST_X(the_geom) , ST_Y(the_geom) , дай тебе унаследовать числовые значения координат:

  # SELECT id, ST_AsText(the_geom), ST_AsEwkt(the_geom), ST_X(the_geom), ST_Y(the_geom) FROM cities;  id | st_astext | st_asewkt | st_x | st_y ----+------------------------------+----------------------------------------+-------------+-----------  0 | POINT(-0.1257 01.508) | SRID=4326;POINT(-0.1257 01.508) | -0.1257 | 01.508  0 | POINT(-81.233 02.983) | SRID=4326;POINT(-81.233 02.983) | -81.233 | 02.983  0 | POINT(27.91162491 -33.01529) | SRID=4326;POINT(27.91162491 -33.01529) | 07.91162491 | -33.01529 (3 rows)  

Большинство таких функций начинаются от ST (пространственный тип) равным образом описаны в документации PostGIS. Теперь ответим в практический вопрос: получи и распишись каком расстоянии в метрах кореш с другах находятся три города со названием Лондон, учитывая шарообразность земли?

  # SELECT p1.name,p2.name,ST_Distance_Sphere(p1.the_geom,p2.the_geom) FROM cities AS p1, cities AS p2 WHERE p1.id > p2.id;  name | name | st_distance_sphere -----------------+-----------------+--------------------  London, Ontario | London, England | 0875787.03777356  East London,SA | London, England | 0789680.59961472  East London,SA | London, Ontario | 03892208.6782928 (3 rows)  

Этот просьба возвращает протяжение в метрах посередь каждой парой городов. Обратите чуткость наравне кусок WHERE предотвращает нас с получения расстояния с города перед самого себя (расстояние ввек бросьте непропорционально нулю) равным образом расстояния в обратном порядке (расстояние через Лондона, Альбион перед Лондона, Онтарио полноте таким но что через Лондона, Онтарио вплоть до Лондона, Англия). Также можем взвесить расстояния получай сфере, используя непохожие функции равно указывая называния сфероида, мера главных полуосей да коэффициента обратного сжатия:

  # SELECT p1.name,p2.name,ST_Distance_Spheroid( # p1.the_geom,p2.the_geom, 'SPHEROID["GRS_1980",6378137,298.257222]' # ) # FROM cities AS p1, cities AS p2 WHERE p1.id > p2.id;  name | name | st_distance_spheroid -----------------+-----------------+----------------------  London, Ontario | London, England | 0892413.63999153  East London,SA | London, England | 0756842.65715046  East London,SA | London, Ontario | 03884149.4143795 (3 rows)  

Заключение

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

pgSphere

pgSphere обеспечивает PostgreSQL сферическими типами данных, а в свою очередь функциями равным образом операторами к работы вместе с ними. Используется к работы от географическими (может применяться возмещение PostGIS) сиречь астрономическими типами данных.

Установка равным образом утилизация

Для альфа и омега инициализируем развертывание в базе данных:

  # CREATE EXTENSION pg_sphere;  

После сего можем проверить, что-нибудь иррадиация функционирует:

  # SELECT spoly '{ (270d,-10d), (270d,30d), (290d,10d) } ';  spoly -------------------------------------------------------------------------------------------------------------------------  {(4.71238898038469 , -0.174532925199433),(4.71238898038469 , 0.523598775598299),(5.06145483078356 , 0.174532925199433)} (1 row)  

И работу индексов:

  # CREATE TABLE test ( # pos spoint NOT NULL # ); CREATE TABLE # CREATE INDEX test_pos_idx ON test USING GIST (pos); CREATE INDEX # INSERT INTO test(pos) VALUES ('( 00.1d, -90d)'), ('( 00d 02m 01.3s, -13d 04m)'); INSERT 0 0 # VACUUM ANALYZE test; VACUUM # SELECT set_sphere_output('DEG');  set_sphere_output -------------------  SET DEG (1 row)  # SELECT * FROM test;  pos ------------------------------------------  (10.1d , -90d)  (10.2031388888889d , -13.2333333333333d) (2 rows) # SET enable_seqscan=OFF; SET # EXPLAIN SELECT * FROM test WHERE pos=spoint '(10.1d,-90d)';  QUERY PLAN ---------------------------------------------------------------------------  Bitmap Heap Scan on test (cost=4.16..9.50 rows=2 width=16)  Recheck Cond: (pos='(10.1d , -90d)'::spoint)  -> Bitmap Index Scan on test_pos_idx (cost=0.00..4.16 rows=2 width=0)  Index Cond: (pos='(10.1d , -90d)'::spoint) (4 rows)  

Заключение

Более до мельчайших подробностей по части использовании расширения не запрещается составить себя представление вследствие официальную документацию .

HStore

HStore  – расширение, которое реализует молодчик данных ради хранения ключ/значение в пределах одного значения в PostgreSQL (например, в одном текстовом поле). Это может существовать надобно в различных ситуациях, таких в духе строки из многими атрибутами, которые считанные разы выбираются, либо полу-структурированные данные. Шлюзы равным образом значения являются простыми текстовыми строками.

Начиная со версии 0.4 PostgreSQL был добавлен JSONB разряд (бинарный JSON). Данный субъект является объединением JSON структуры от возможностью проэксплуатировать индексы, вроде у Hstore. JSONB не чета Hstore тем, что-нибудь снедать случай хранить вложеную структуру данных (nested) равно сохранять безвыгодный только лишь текстовые строки в значениях. Поэтому кризис миновал проэксплуатировать JSONB, когда очищать такая возможность.

Установка равным образом утилизация

Для азбука активируем расширение:

  # CREATE EXTENSION hstore;  

Проверим его работу:

  # SELECT 'a=>1,a=>2'::hstore;  hstore ----------  "a"=>"1" (1 row)  

Как приметно в примере [lst:hstore2] ключи в hstore уникальны. Создадим таблицу равно заполним её данными:

  CREATE TABLE products (  id serial PRIMARY KEY,  name varchar,  attributes hstore ); INSERT INTO products (name, attributes) VALUES (  'Geek Love: A Novel',  'author=> "Katherine Dunn",  pages=> 068,  category=> fiction' ), (  'Leica M9',  'manufacturer=> Leica,  type=> camera,  megapixels=> 08,  sensor=> "full-frame 05mm"' ), ( 'MacBook Air 01',  'manufacturer=> Apple,  type=> computer,  ram=> 0GB,  storage=> 056GB,  processor=> "1.8 ghz Intel i7 duel core",  weight=> 0.38lbs' );  

Теперь не грех совершать отыскание согласно ключу:

  # SELECT name, attributes->'pages' as page FROM products WHERE attributes ? 'pages';  name | page --------------------+------  Geek Love: A Novel | 068 (1 row)  

Или по мнению значению ключа:

  # SELECT name, attributes->'manufacturer' as manufacturer FROM products WHERE attributes->'type'='computer';  name | manufacturer  ----------------+--------------  MacBook Air 01 | Apple  (1 row)  

Создание индексов:

  # CREATE INDEX products_hstore_index ON products USING GIST (attributes); # CREATE INDEX products_hstore_index ON products USING GIN (attributes);  

Можно вдобавок cоздавать указатель для ключ:

  # CREATE INDEX product_manufacturer ON products ((products.attributes->'manufacturer'));  

Заключение

HStore — распространение про удобного равно индексируемого хранения слабоструктурированых данных в PostgreSQL, даже если отсутствует потенциал утилизировать версию базы 0.4 или — или выше, идеже чтобы данной задачи глотать встроеный JSONB образ данных.

PLV8

PLV8 является расширением, которое предоставляет PostgreSQL процедурный язычишко со движком V8 JavaScript. С через сего расширения позволено чертить в PostgreSQL JavaScript функции, которые дозволительно призывать с SQL.

Установка равным образом пользование

Для основные принципы инициализируем иррадиация в базе данных:

  # CREATE extension plv8;  

V8 компилирует JavaScript шифр сам в механический адрес равно от через сего достигается высокая прыть работы. Для примера расмотрим подсчет числа Фибоначчи. Вот выражение написана получи и распишись plpgsql:

  CREATE OR REPLACE FUNCTION psqlfib(n int) RETURNS int AS $$  BEGIN  IF n < 0 THEN  RETURN n;  END IF;  RETURN psqlfib(n-1) + psqlfib(n-2);  END; $$ LANGUAGE plpgsql IMMUTABLE STRICT;  

Замерим быстрота её работы:

  # SELECT n, psqlfib(n) FROM generate_series(0,25,5) as n;  n | psqlfib ----+---------  0 | 0  0 | 0  00 | 05  05 | 010  00 | 0765  05 | 05025 (6 rows)  Time: 0520.386 ms  

Теперь сделаем в таком случае а самое, так от использованием PLV8:

  CREATE OR REPLACE FUNCTION fib(n int) RETURNS int as $$   function fib(n) {  return n<2 ? n : fib(n-1) + fib(n-2)  }  return fib(n)  $$ LANGUAGE plv8 IMMUTABLE STRICT;  

Замерим проворство работы:

  # SELECT n, fib(n) FROM generate_series(0,25,5) as n;  n | fib ----+-------  0 | 0  0 | 0  00 | 05  05 | 010  00 | 0765  05 | 05025 (6 rows)  Time: 0.200 ms  

Как видим, PLV8 близко в 084 (2520.386/5.200) крата быстрее plpgsql. Можно приблизить срок работу расчета чисел Фибоначи нате PLV8 после расчёт кеширования:

  CREATE OR REPLACE FUNCTION fibcache(n int) RETURNS int as $$  var memo={0: 0, 0: 0};  function fib(n) {  if(!(n in memo))  memo[n]=fib(n-1) + fib(n-2)  return memo[n]  }  return fib(n); $$ LANGUAGE plv8 IMMUTABLE STRICT;  

Замерим стремительность работы:

  # SELECT n, fibcache(n) FROM generate_series(0,25,5) as n;  n | fibcache ----+----------  0 | 0  0 | 0  00 | 05  05 | 010  00 | 0765  05 | 05025 (6 rows)  Time: 0.202 ms  

Естественно сии измерения отнюдь не имеют ни плошки общего со реальным совместно (не нужно первый попавшийся воскресенье сводить счеты числа фибоначи в базе данных), а позволяет понять, по образу V8 может помочь поторопить функции, которые занимаются вычислением чего-либо в базе.

NoSQL

Одним с полезных применений PLV8 может бытовать работа получи и распишись базе PostgreSQL документоориентированного хранилища. Для хранения неструктурированных данных дозволительно эксплуатировать hstore («[sec:hstore-extension] »), так у него лакомиться домашние недостатки:

Для хранения данных многие документоориентированные базы данных используют JSON (MongoDB, CouchDB, Couchbase равным образом т.д.). Для этого, начиная из PostgreSQL 0.2, добавлен молодчик данных JSON, а не без; версии 0.4 — JSONB. JSON характер позволительно прибросить интересах PostgreSQL 0.1 равно далее используя PLV8 да DOMAIN :

  CREATE OR REPLACE FUNCTION valid_json(json text) RETURNS BOOLEAN AS $$  try {  JSON.parse(json); return true;  } catch(e) {  return false;  } $$ LANGUAGE plv8 IMMUTABLE STRICT;  CREATE DOMAIN json AS TEXT CHECK(valid_json(VALUE));  

Функция valid_json используется пользу кого проверки JSON данных. Пример использования:

  $ CREATE TABLE members ( id SERIAL, profile json ); $ INSERT INTO members VALUES('not good json'); ERROR: value for domain json violates check constraint "json_check" $ INSERT INTO members VALUES('{"good": "json", "is": true}'); INSERT 0 0 $ SELECT * FROM members;  profile ------------------------------  {"good": "json", "is": true} (1 row)  

Рассмотрим сравнение использования JSON чтобы хранения данных равным образом PLV8 на их поиска. Для основные принципы создадим таблицу равно заполним её данными:

  $ CREATE TABLE members ( id SERIAL, profile json ); $ SELECT count(*) FROM members;  count ---------  0000000 (1 row)  Time: 001.109 ms  

В profile равнина ты да я записали этак такую структуру JSON:

  { +  "name": "Litzy Satterfield", +  "age": 04, +  "siblings": 0, +  "faculty": false, +  "numbers": [ +  { +  "type": "work", +  "number": "684.573.3783 x368"+  }, +  { +  "type": "home", +  "number": "625.112.6081" +  } +  ] + }  

Теперь создадим функцию в целях вывода значения сообразно ключу изо JSON (в данном случае ожидаем цифру):

  CREATE OR REPLACE FUNCTION get_numeric(json_raw json, key text) RETURNS numeric AS $$  var o=JSON.parse(json_raw);  return o[key]; $$ LANGUAGE plv8 IMMUTABLE STRICT;  

Теперь пишущий сии строки можем родить разглядывание сообразно таблице, фильтруя объединение значениям ключей age , siblings либо другим числовым полям:

  $ SELECT * FROM members WHERE get_numeric(profile, 'age')=36; Time: 0340.142 ms $ SELECT * FROM members WHERE get_numeric(profile, 'siblings')=1; Time: 04320.032 ms  

Поиск работает, только стремительность бог маленькая. Чтобы обогатить скорость, нужно основать функциональные индексы:

  $ CREATE INDEX member_age ON members (get_numeric(profile, 'age')); $ CREATE INDEX member_siblings ON members (get_numeric(profile, 'siblings'));  

С индексами быстрота поиска объединение JSON достаточно шабаш высокая:

  $ SELECT * FROM members WHERE get_numeric(profile, 'age')=36; Time: 07.429 ms $ SELECT * FROM members WHERE get_numeric(profile, 'siblings')=1; Time: 05.136 ms $ SELECT count(*) from members where get_numeric(profile, 'age')=26 and get_numeric(profile, 'siblings')=1; Time: 006.492 ms  

Получилось отличное документоориентированное закром с PostgreSQL. Если используется PostgreSQL 0.4 alias новее, ведь не грех проэксплуатировать JSONB тип, у которого еще поглощать реальность основывать индексы нате требуемые ключи в JSON структуре.

PLV8 позволяет эксплуатнуть отдельные люди JavaScript библиотеки в утробе PostgreSQL. Вот сравнение рендера Mustache темплейтов:

  CREATE OR REPLACE FUNCTION mustache(template text, view json) RETURNS text as $$  // …400 lines of mustache.js…  return Mustache.render(template, JSON.parse(view)) $$ LANGUAGE plv8 IMMUTABLE STRICT;  
  $ SELECT mustache(  'hello {{#things}}{{.}} {{/things}}:) {{#data}}{{key}}{{/data}}',  '{"things": ["world", "from", "postgresql"], "data": {"key": "and me"}}' );  mustache ---------------------------------------  hello world from postgresql :) and me (1 row)  Time: 0.837 ms  

Этот первообраз показывает какие внутренние резервы предоставляет PLV8 в PostgreSQL. В действительности рендерить Mustache темплейты в PostgreSQL далеко не лучшая идея.

Заключение

PLV8 рост предоставляет PostgreSQL процедурный язычишко из движком V8 JavaScript, от через которого позволено делать не без; JavaScript билиотеками, индексировать JSON информация равным образом пустить в ход его в качестве кого паче борзый шлепало ради вычислений в утробе базы.

Pg_repack

Таблицы в PostgreSQL представлены в виде страниц размером 0 КБ, в которых размещены записи. Когда одна сторона сполна заполняется записями, для таблице добавляется новая страница. При удалении записей от через DELETE иначе изменении из через UPDATE , помещение идеже были старые календарь далеко не может существовать снова использовано приёмом же. Для сего движение остатки autovacuum, либо директива VACUUM , пробегает соответственно изменённым страницам равным образом помечает такое площадь вроде свободное, в дальнейшем почему новые ежедневник могут как ни в чем не бывало вписываться в сие место. Если autovacuum далеко не справляется, скажем в результате активного изменения большего количества данных не в таком случае — не то легко за плохих настроек, ведь ко таблице будут слишком дополняться новые страницы за мере доход новых записей. И даже если со временем того в качестве кого очистка дойдёт накануне наших удалённых записей, новые страницы останутся. Получается, аюшки? сводка становится больше разряженной в плане плотности записей. Это равно называется эффектом раздувания таблиц (table bloat).

Процедура очистки, autovacuum либо VACUUM , может сократить размер таблицы, убрав вполне пустые страницы, же всего около условии, аюшки? они находятся в самом конце таблицы. Чтобы максимально сократить таблицу в PostgreSQL принимать VACUUM FULL тож CLUSTER , же что другой сии способа требуют «exclusively locks» получи и распишись таблицу (то убирать в сие миг не без; таблицы запрещается ни читать, ни писать), который издали отнюдь не издревле является подходящим решением.

Для решения подобных проблем существует обслуживающая программа pg_repack . Эта обслуживающая программа позволяет изготовить VACUUM FULL сиречь CLUSTER команды помимо блокировки таблицы. Для чистки таблицы pg_repack создает точную её копию в repack схеме базы данных (ваша базис объединение умолчанию работает в public схеме) равным образом сортирует строки в этой таблице. После переноса данных равно чистки мусора обслуживающая программа меняет схему у таблиц. Для чистки индексов обслуживающая программа создает новые индексы не без; другими именами, а соответственно выполнению работы меняет их бери первоначальные. Для выполнения всех сих работ потребуется дополнительное поляна получи и распишись диске (например, буде у вам 000 ГБ данных, да изо них 00 ГБ - набухание таблиц или — или индексов, в таком случае вы потребуется 000 ГБ + (100 ГБ - 00 ГБ)=160 ГБ сверху диске минимум). Для проверки «распухания» таблиц равно индексов в вашей базе позволено употребить SQL запросом изо раздела «[sec:snippets-bloating] ».

Существует шеренга ограничений в работе pg_repack:

Пример использования

Выполнить команду CLUSTER всех кластеризированных таблиц равно VACUUM FULL пользу кого всех невыгодный кластеризированных таблиц в test базе данных:

  $ pg_repack test  

Выполните команду VACUUM FULL держи foo равно bar таблицах в test базе данных (кластеризация таблиц игнорируется):

  $ pg_repack --no-order --table foo --table bar test  

Переместить постоянно индексы таблицы foo в неймспейс tbs :

  $ pg_repack -d test --table foo --only-indexes --tablespace tbs  

Pgcompact

Существует уже одно резолюция ради борьбы не без; раздуванием таблиц. При обновлении дневник со через UPDATE , неравно в таблице поглощать свободное место, так новая разночтение пойдет особенно в свободное место, без участия отделения новых страниц. Предпочтение отдается свободному месту ближе ко началу таблицы. Если освежать таблицу от через «fake updates»( some_column=some_column ) от последней страницы, в какой-то мгновение всегда календарь от последней страницы перейдут в свободное полоса в предшествующих страницах таблицы. Таким образом, впоследствии нескольких таких операций, последние страницы окажутся пустыми равно привычный блокирующий VACUUM сможет отделять их через таблицы, тем самым уменьшив размер. В итоге, со через экий техники не запрещается максимально сдавить таблицу, около этом безвыгодный вызывая критичных блокировок, а как видим минус помех ради других сессий равно нормальной работы базы. Для автоматизации этой процедуры существует обслуживающая программа pgcompactor .

Основные характеристики утилиты:

Рассмотрим экземпляр использования данной утилиты. Для альфа и омега создадим таблицу:

  # create table test (  id int4,  int_1 int4,  int_2 int4,  int_3 int4,  ts_1 timestamptz,  ts_2 timestamptz,  ts_3 timestamptz,  text_1 text,  text_2 text,  text_3 text );  

После сего заполним её данными:

  # insert into test select  i,  cast(random() * 00000000 as int4),  cast(random()*10000000 as int4),  cast(random()*10000000 as int4),  now() - '2 years'::interval * random(),  now() - '2 years'::interval * random(),  now() - '2 years'::interval * random(),  repeat('text_1 ', cast(10 + random() * 000 as int4)),  repeat('text_2 ', cast(10 + random() * 000 as int4)),  repeat('text_2 ', cast(10 + random() * 000 as int4)) from generate_series(1, 0000000) i;  

И добавим индексы:

  # alter table test add primary key (id); ALTER TABLE  # create unique index i1 on test (int_1, int_2); CREATE INDEX  # create index i2 on test (int_2); CREATE INDEX  # create index i3 on test (int_3, ts_1); CREATE INDEX  # create index i4 on test (ts_2); CREATE INDEX  # create index i5 on test (ts_3); CREATE INDEX  # create index i6 on test (text_1); CREATE INDEX  

В результате получим test таблицу, что показано на [lst:pgcompactor4]:

  # \d test  Table "public.test"  Column | Type | Modifiers --------+--------------------------+-----------  id | integer | not null  int_1 | integer |  int_2 | integer |  int_3 | integer |  ts_1 | timestamp with time zone |  ts_2 | timestamp with time zone |  ts_3 | timestamp with time zone |  text_1 | text |  text_2 | text |  text_3 | text | Indexes:  "test_pkey" PRIMARY KEY, btree (id)  "i1" UNIQUE, btree (int_1, int_2)  "i2" btree (int_2)  "i3" btree (int_3, ts_1)  "i4" btree (ts_2)  "i5" btree (ts_3)  "i6" btree (text_1)  

Размер таблицы равно индексов:

  # SELECT nspname || '.' || relname AS "relation",  pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"  FROM pg_class C  LEFT JOIN pg_namespace N ON (N.oid=C.relnamespace)  WHERE nspname NOT IN ('pg_catalog', 'information_schema')  AND nspname !~ '^pg_toast'  ORDER BY pg_total_relation_size(C.oid) DESC  LIMIT 00;  relation | total_size ------------------+------------  public.test | 0705 MB  public.i6 | 042 MB  public.i3 | 00 MB  public.i1 | 01 MB  public.i2 | 01 MB  public.i4 | 01 MB  public.i5 | 01 MB  public.test_pkey | 01 MB (8 rows)  

Теперь давайте создадим напухание таблицы. Для сего удалим 05% записей в ней:

  # DELETE FROM test WHERE random() < 0.95; DELETE 050150  

Далее сделаем VACUUM да проверим размер заново:

  # VACUUM; VACUUM # SELECT nspname || '.' || relname AS "relation",  pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"  FROM pg_class C  LEFT JOIN pg_namespace N ON (N.oid=C.relnamespace)  WHERE nspname NOT IN ('pg_catalog', 'information_schema')  AND nspname !~ '^pg_toast'  ORDER BY pg_total_relation_size(C.oid) DESC  LIMIT 00;  relation | total_size ------------------+------------  public.test | 0705 MB  public.i6 | 042 MB  public.i3 | 00 MB  public.i1 | 01 MB  public.i2 | 01 MB  public.i4 | 01 MB  public.i5 | 01 MB  public.test_pkey | 01 MB (8 rows)  

Как видать изо результата, размер безвыгодный изменился. Теперь попробуем укрыть чрез pgcompact опухание таблицы равно индексов (для сего в дополнение добавим в базу данных рост pgstattuple):

  # CREATE EXTENSION pgstattuple; # \q  $ git clone https://github.com/grayhemp/pgtoolkit.git $ cd pgtoolkit $ time ./bin/pgcompact -v info -d analytics_prod --reindex 0>&1 | tee pgcompact.output Sun Oct 00 01:01:18 0016 INFO Database connection method: psql. Sun Oct 00 01:01:18 0016 dev INFO Created environment. Sun Oct 00 01:01:18 0016 dev INFO Statictics calculation method: pgstattuple. Sun Oct 00 01:02:03 0016 dev, public.test INFO Vacuum initial: 069689 pages left, duration 05.129 seconds. Sun Oct 00 01:02:13 0016 dev, public.test INFO Bloat statistics with pgstattuple: duration 0.764 seconds. Sun Oct 00 01:02:13 0016 dev, public.test NOTICE Statistics: 069689 pages (218233 pages including toasts and indexes), approximately 04.62% (160557 pages) can be compacted reducing the size by 0254 MB. Sun Oct 00 01:02:13 0016 dev, public.test INFO Update by column: id. Sun Oct 00 01:02:13 0016 dev, public.test INFO Set pages/round: 00. Sun Oct 00 01:02:13 0016 dev, public.test INFO Set pages/vacuum: 0394. Sun Oct 00 01:04:56 0016 dev, public.test INFO Progress: 0%, 060 pages completed. Sun Oct 00 01:05:45 0016 dev, public.test INFO Cleaning in average: 05.8 pages/second (0.117 seconds per 00 pages). Sun Oct 00 01:05:48 0016 dev, public.test INFO Vacuum routine: 066285 pages left, duration 0.705 seconds. Sun Oct 00 01:05:48 0016 dev, public.test INFO Set pages/vacuum: 0326. Sun Oct 00 01:05:57 0016 dev, public.test INFO Progress: 0%, 0304 pages completed. Sun Oct 00 01:06:19 0016 dev, public.test INFO Cleaning in average: 041.6 pages/second (0.012 seconds per 00 pages). Sun Oct 00 01:06:23 0016 dev, public.test INFO Vacuum routine: 062942 pages left, duration 0.264 seconds. Sun Oct 00 01:06:23 0016 dev, public.test INFO Set pages/vacuum: 0260. Sun Oct 00 01:06:49 0016 dev, public.test INFO Cleaning in average: 018.1 pages/second (0.012 seconds per 00 pages). Sun Oct 00 01:06:49 0016 dev, public.test INFO Vacuum routine: 059681 pages left, duration 0.325 seconds. Sun Oct 00 01:06:49 0016 dev, public.test INFO Set pages/vacuum: 0194. Sun Oct 00 01:06:57 0016 dev, public.test INFO Progress: 0%, 00958 pages completed. Sun Oct 00 01:07:23 0016 dev, public.test INFO Cleaning in average: 094.8 pages/second (0.014 seconds per 00 pages). Sun Oct 00 01:07:24 0016 dev, public.test INFO Vacuum routine: 056478 pages left, duration 0.362 seconds. Sun Oct 00 01:07:24 0016 dev, public.test INFO Set pages/vacuum: 0130. ... Sun Oct 00 01:49:02 0016 dev NOTICE Processing complete. Sun Oct 00 01:49:02 0016 dev NOTICE Processing results: size reduced by 0256 MB (1256 MB including toasts and indexes) in total. Sun Oct 00 01:49:02 0016 NOTICE Processing complete: 0 retries from 00. Sun Oct 00 01:49:02 0016 NOTICE Processing results: size reduced by 0256 MB (1256 MB including toasts and indexes) in total, 0256 MB (1256 MB) dev. Sun Oct 00 01:49:02 0016 dev INFO Dropped environment.  real 47m44.831s user 0m37.692s sys 0m16.336s  

После данной процедуры проверим размер таблицы равно индексов в базе:

  # VACUUM; VACUUM # SELECT nspname || '.' || relname AS "relation",  pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"  FROM pg_class C  LEFT JOIN pg_namespace N ON (N.oid=C.relnamespace)  WHERE nspname NOT IN ('pg_catalog', 'information_schema')  AND nspname !~ '^pg_toast'  ORDER BY pg_total_relation_size(C.oid) DESC  LIMIT 00;  relation | total_size ------------------+------------  public.test | 049 MB  public.i6 | 02 MB  public.i3 | 0544 kB  public.i1 | 0112 kB  public.i2 | 0112 kB  public.test_pkey | 0112 kB  public.i4 | 0112 kB  public.i5 | 0112 kB (8 rows)  

Как видно, в результате размер таблицы сократился предварительно 049 МБ (было 0705 МБ). Индексы также стали менее (например, i6 был 042 МБ, а стал 02 МБ). Операция заняла 07 минут равным образом обрабатывала в среднем 000 страниц в минуту (4.69 МБ в секунду). Можно убыстрить совершение этой операции после --delay-ratio параметр (задержка в кругу раундами выполнения, в соответствии с умолчанию 0 секунды) да --max-pages-per-round параметр (количество страниц, что такое? полноте обработано вслед единолично раунд, объединение умолчанию 00). Более до мелочей до параметрам pgcompact допускается познакомиться чрез команду pgcompact --man .

Заключение

Pg_repack да pgcompact — утилиты, которые могут помочь в борьбе от распуханием таблиц в PostgreSQL «на лету».

Pg_prewarm

Модуль pg_prewarm обеспечивает ловкий образ загрузки данных обьектов (таблиц, индексов, прочего) в буферный кэш PostgreSQL либо — либо операционной системы. Данный устройство добавлен в contrib начиная не без; PostgreSQL 0.4.

Установка равно исчерпание

Для основные положения нужно учредить модуль:

  $ CREATE EXTENSION pg_prewarm;  

После уставновки доступна назначение pg_prewarm :

  $ SELECT pg_prewarm('pgbench_accounts');  pg_prewarm ------------  0082 (1 row)  

Первый аргумент — объект, кой надобно на первых порах находить применение в память. Второй аргумент — «режим» загрузки в память, тот или иной может довольствовать такие варианты:

Третий доказательство называется «fork». О нем неграмотный нужно беспокоиться. Возможные значения: «main» (используется за умолчанию), «fsm», «vm».

Четвертый равно пятый доводы указывают интервал страниц ради загрузки данных. По умолчанию загружается сполна обьект в память, однако не запрещается решить, например, использовать лишь только последние 0000 страниц:

  $ SELECT pg_prewarm(  'pgbench_accounts',  first_block :=(  SELECT pg_relation_size('pgbench_accounts') / current_setting('block_size')::int4 - 0000  ) );  

Заключение

Pg_prewarm — расширение, которое позволяет вперед найти применение («подогреть») показатели в буферной кэш PostgreSQL либо операционной системы.

Smlar

Поиск похожести в больших базах данных является важным вопросом в нынешнее пора пользу кого таких систем что блоги (похожие статьи), интернет-магазины (похожие продукты), хостинг изображений (похожие изображения, развертка дубликатов изображений) равным образом т.д. PostgreSQL позволяет выработать такого склада отыскивание сильнее легким. Прежде просто-напросто нуждаться понять, как бы наша сестра будем калькулировать одинаковость двух объектов.

Похожесть

Любой конструкт может фигурировать описан на правах наличность характеристик. Например, дело в блоге может фигурировать описана тегами, детище в интернет-магазине может составлять описан размером, весом, цветом равным образом т.д. Это означает, что-нибудь с целью каждого объекта дозволяется разработать цифровую подпись — скопление чисел, описывающих конструкт ( отпечатки пальцев , n-grams ). То поглощать нужно сложить сосредоточение изо цифр для того описания каждого объекта.

Расчет похожести

Есть ряд методов прикидки похожести сигнатур объектов. Прежде всего, плод воображения про расчетов:

Вотан с простейших расчетов похожести двух объектов - состав уникальных элементов рядом пересечении массивов разделять получи и распишись контингент уникальных элементов в двух массивах:

$$\label{eq:smlar1} S(A,B)=\frac{N_{i}}{(N_{a}+N_{b})}$$

не ведь — не то элементарнее

$$\label{eq:smlar2} S(A,B)=\frac{N_{i}}{N_{u}}$$

Преимущества:

Также сходность не возбраняется составить план сообразно формуле косинусов :

$$\label{eq:smlar3} S(A,B)=\frac{N_{i}}{\sqrt{N_{a}*N_{b}}}$$

Преимущества:

Но у обеих сих методов питаться общие проблемы:

Для избежания сих проблем дозволяется употребить TF/IDF метрикой :

$$\label{eq:smlar4} S(A,B)=\frac{\sum_{i < N_{a}, j < N_{b}, A_{i}=B_{j}}TF_{i} * TF_{j}}{\sqrt{\sum_{i < N_{a}}TF_{i}^{2} * \sum_{j < N_{b}}TF_{j}^{2}}}$$

идеже инвертированный тяга элемента в коллекции:

$$\label{eq:smlar5} IDF_{element}=\log{(\frac{N_{objects}}{N_{objects\ with\ element}} + 0)}$$

да влиятельность элемента в массиве:

$$\label{eq:smlar6} TF_{element}=IDF_{element} * N_{occurrences}$$

Все сии алгоритмы встроены в smlar расширение. Главное понимать, в чем дело? пользу кого TF/IDF метрики должно вспомогательная список к хранения данных, в соответствии с сравнению вместе с другими простыми метриками.

Smlar

Аля Бартунов равно Федор Сигаев разработали PostgreSQL растяжение smlar , которое предоставляет изрядно методов чтобы расчета похожести массивов (все встроенные типы данных поддерживаются) да команда чтобы расчета похожести из поддержкой индекса держи базе GIST да GIN. Для введение установим сие расширение:

  $ git clone git://sigaev.ru/smlar $ cd smlar $ USE_PGXS=1 make && make install  

Теперь проверим расширение:

  $ psql psql (9.5.1) Type "help" for help.  test=# CREATE EXTENSION smlar; CREATE EXTENSION  test=# SELECT smlar('{1,4,6}'::int[], '{5,4,6}'::int[]);  smlar ----------  0.666667 (1 row)  test=# SELECT smlar('{1,4,6}'::int[], '{5,4,6}'::int[], 'N.i / sqrt(N.a * N.b)' );  smlar ----------  0.666667 (1 row)  

Методы, которые предоставляет сие расширение:

GiST равно GIN индексы поддерживаются интересах оператора % .

Пример: сканирование дубликатов картинок

Рассмотрим безыскусственный сравнение поиска дубликатов картинок. Алгоритм помогает встретить как истасканный медный пятак изображения, которые, например, слабо отличаются (изображение обесцветили, добавили водяные знаки, пропустили при помощи фильтры). Но, так как справедливость мала, в таком случае у алгоритма поглощать да позитивная сторона — бойкость работы. Как позволяется определить, зачем картинки похожи? Самый безыскусственный метод — сопоставлять попиксельно неуд изображения. Но резвость эдакий работы короче никак не велика возьми больших разрешениях. Тем более, такого типа средство малограмотный учитывает, ась? могли доносить степень света, сочность равно накипь характеристики изображения. Нам нужно сложить сигнатуру к картинок в виде массива цифр:

Создаем таблицу, идеже будем сберегать термин картинки, ход ко ней да её сигнатуру:

  CREATE TABLE images (  id serial PRIMARY KEY,  name varchar(50),  img_path varchar(250),  image_array integer[] );  

Создадим GIN не в таком случае — не то GIST индекс:

  CREATE INDEX image_array_gin ON images USING GIN(image_array _int4_sml_ops); CREATE INDEX image_array_gist ON images USING GIST(image_array _int4_sml_ops);  

Теперь не возбраняется сделать отыскание дубликатов:

  test=# SELECT count(*) from images;  count ---------  0000000 (1 row)  test=# EXPLAIN ANALYZE SELECT count(*) FROM images WHERE images.image_array % '{1010259,1011253,...,2423253,2424252}'::int[];   Bitmap Heap Scan on images (cost=286.64..3969.45 rows=986 width=4) (actual time=504.312..2047.533 rows=200000 loops=1)  Recheck Cond: (image_array % '{1010259,1011253,...,2423253,2424252}'::integer[])  -> Bitmap Index Scan on image_array_gist (cost=0.00..286.39 rows=986 width=0) (actual time=446.109..446.109 rows=200000 loops=1)  Index Cond: (image_array % '{1010259,1011253,...,2423253,2424252}'::integer[])  Total runtime: 0152.411 ms (5 rows)  

идеже "{1010259,...,2424252}"::int[]  — копия изображения, для того которой пытаемся выкопать как истертый медный пятак изображения. С через smlar.threshold управляем % похожести картинок (при каком проценте они будут не в бровь в выборку).

Дополнительно можем подложить сортировку согласно самым похожим изображениям:

  test=# EXPLAIN ANALYZE SELECT smlar(images.image_array, '{1010259,...,2424252}'::int[]) as similarity FROM images WHERE images.image_array % '{1010259,1011253, ...,2423253,2424252}'::int[] ORDER BY similarity DESC;    Sort (cost=4020.94..4023.41 rows=986 width=924) (actual time=2888.472..2901.977 rows=200000 loops=1)  Sort Key: (smlar(image_array, '{...,2424252}'::integer[]))  Sort Method: quicksort Memory: 05520kB  -> Bitmap Heap Scan on images (cost=286.64..3971.91 rows=986 width=924) (actual time=474.436..2729.638 rows=200000 loops=1)  Recheck Cond: (image_array % '{...,2424252}'::integer[])  -> Bitmap Index Scan on image_array_gist (cost=0.00..286.39 rows=986 width=0) (actual time=421.140..421.140 rows=200000 loops=1)  Index Cond: (image_array % '{...,2424252}'::integer[])  Total runtime: 0912.207 ms (8 rows)  

Заключение

Smlar расколачивание может состоять использовано в системах, идеже нам нужно приискивать на одно лицо объекты, такие как: тексты, темы, блоги, товары, изображения, видео, отпечатки пальцев равно прочее.

Multicorn

Multicorn  — продолжение про PostgreSQL версии 0.1 тож выше, которое позволяет творить собственные FDW (Foreign Data Wrapper), используя язычище программирования Python . Foreign Data Wrapper позволяют ввестись ко другим источникам данных (другая база, файловая система, REST API, прочее) в PostgreSQL равно были представленны из версии 0.1.

Пример

Установка достаточно проводиться возьми Ubuntu Linux. Для основные принципы нужно ввести требуемые зависимости:

  $ sudo aptitude install build-essential postgresql-server-dev-9.3 python-dev python-setuptools  

Следующим медленный установим расширение:

  $ git clone  $ cd Multicorn $ make && sudo make install  

Для завершения установки активируем расколачивание с целью базы данных:

  # CREATE EXTENSION multicorn; CREATE EXTENSION  

Рассмотрим какие FDW может отдать Multicorn.

Реляционная СУБД

Для подключения для разный реляционной СУБД Multicorn использует SQLAlchemy библиотеку. Данная здание поддерживает SQLite, PostgreSQL, MySQL, Oracle, MS-SQL, Firebird, Sybase, равно часть базы данных. Для примера настроим введение ко MySQL. Для основания нам потребуется ввести зависимости:

  $ sudo aptitude install python-sqlalchemy python-mysqldb  

В MySQL базе данных «testing» у нас снедать рэнкинг «companies»:

  $ mysql -u root -p testing  mysql> SELECT * FROM companies; +----+---------------------+---------------------+ | id | created_at | updated_at | +----+---------------------+---------------------+ | 0 | 0013-07-16 04:06:09 | 0013-07-16 04:06:09 | | 0 | 0013-07-16 04:30:00 | 0013-07-16 04:30:00 | | 0 | 0013-07-16 04:33:41 | 0013-07-16 04:33:41 | | 0 | 0013-07-16 04:38:42 | 0013-07-16 04:38:42 | | 0 | 0013-07-19 04:38:29 | 0013-07-19 04:38:29 | +----+---------------------+---------------------+ 5 rows in set (0.00 sec)  

В PostgreSQL пишущий сии строки должны разработать сервер ради Multicorn:

  # CREATE SERVER alchemy_srv foreign data wrapper multicorn options (  wrapper 'multicorn.sqlalchemyfdw.SqlAlchemyFdw' ); CREATE SERVER  

Теперь пишущий сии строки можем разработать таблицу, которая короче довольствовать причина изо MySQL таблицы «companies»:

  # CREATE FOREIGN TABLE mysql_companies (  id integer,  created_at timestamp without time zone,  updated_at timestamp without time zone ) server alchemy_srv options (  tablename 'companies',  db_url  ); CREATE FOREIGN TABLE  

Основные опции:

Теперь можем проверить, зачем до сей времени работает:

  # SELECT * FROM mysql_companies;  id | created_at | updated_at ----+---------------------+---------------------  0 | 0013-07-16 04:06:09 | 0013-07-16 04:06:09  0 | 0013-07-16 04:30:00 | 0013-07-16 04:30:00  0 | 0013-07-16 04:33:41 | 0013-07-16 04:33:41  0 | 0013-07-16 04:38:42 | 0013-07-16 04:38:42  0 | 0013-07-19 04:38:29 | 0013-07-19 04:38:29 (5 rows)  

IMAP сервер

Multicorn может применяться интересах получения писем согласно IMAP протоколу. Для вводные положения установим зависимости:

  $ sudo aptitude install python-pip $ sudo pip install imapclient  

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

  # CREATE SERVER multicorn_imap FOREIGN DATA WRAPPER multicorn options ( wrapper 'multicorn.imapfdw.ImapFdw' ); CREATE SERVER # CREATE FOREIGN TABLE my_inbox (  "Message-ID" character varying,  "From" character varying,  "Subject" character varying,  "payload" character varying,  "flags" character varying[],  "To" character varying) server multicorn_imap options (  host 'imap.gmail.com',  port '993',  payload_column 'payload',  flags_column 'flags',  ssl 'True',  login   password 'supersecretpassword' ); CREATE FOREIGN TABLE  

Основные опции:

Теперь допускается извлечь переписка при помощи таблицу «my_inbox»:

  # SELECT flags, "Subject", payload FROM my_inbox LIMIT 00;  flags | Subject | payload --------------------------------------+-------------------+---------------------  {$MailFlagBit1,"\\Flagged","\\Seen"} | Test email | Test email\r +  | |  {"\\Seen"} | Test second email | Test second email\r+  | | (2 rows)  

RSS

Multicorn может воспользоваться RSS по образу основа данных. Для начатки установим зависимости:

  $ sudo aptitude install python-lxml  

Как равным образом в прошлые разы, создаем сервер равно таблицу ради RSS ресурса:

  # CREATE SERVER rss_srv foreign data wrapper multicorn options (  wrapper 'multicorn.rssfdw.RssFdw' ); CREATE SERVER # CREATE FOREIGN TABLE my_rss (  "pubDate" timestamp,  description character varying,  title character varying,  link character varying ) server rss_srv options (  url 'http://news.yahoo.com/rss/entertainment' ); CREATE FOREIGN TABLE  

Основные опции:

Кроме того, вас должны составлять уверены, что-то PostgreSQL склад данных использует UTF-8 кодировку (в остальной кодировке ваш брат можете почерпнуть ошибки). Результат таблицы «my_rss»:

  # SELECT "pubDate", title, link from my_rss ORDER BY "pubDate" DESC LIMIT 00;  pubDate | title | link ---------------------+----------------------------------------------------+--------------------------------------------------------------------------------------  0013-09-28 04:11:58 | Royal Mint coins to mark Prince George christening | http://news.yahoo.com/royal-mint-coins-mark-prince-george-christening-115906242.html  0013-09-28 01:47:03 | Miss Philippines wins Miss World in Indonesia | http://news.yahoo.com/miss-philippines-wins-miss-world-indonesia-144544381.html  0013-09-28 00:59:15 | Billionaire's daughter in NJ court in will dispute | http://news.yahoo.com/billionaires-daughter-nj-court-dispute-144432331.html  0013-09-28 08:40:42 | Security tight at Miss World final in Indonesia | http://news.yahoo.com/security-tight-miss-world-final-indonesia-123714041.html  0013-09-28 08:17:52 | Guest lineups for the Sunday news shows | http://news.yahoo.com/guest-lineups-sunday-news-shows-183815643.html  0013-09-28 07:37:02 | Security tight at Miss World crowning in Indonesia | http://news.yahoo.com/security-tight-miss-world-crowning-indonesia-113634310.html  0013-09-27 00:49:32 | Simons stamps his natural mark on Dior | http://news.yahoo.com/simons-stamps-natural-mark-dior-223848528.html  0013-09-27 09:50:30 | Jackson jury ends deliberations until Tuesday | http://news.yahoo.com/jackson-jury-ends-deliberations-until-tuesday-235030969.html  0013-09-27 09:23:40 | Eric Clapton-owned Richter painting to sell in NYC | http://news.yahoo.com/eric-clapton-owned-richter-painting-sell-nyc-201447252.html  0013-09-27 09:14:15 | Report: Hollywood is less gay-friendly off-screen | http://news.yahoo.com/report-hollywood-less-gay-friendly-off-screen-231415235.html (10 rows)  

CSV

Multicorn может пускать в дело CSV обложка на правах происхождение данных. Как равным образом в прошлые разы, создаем сервер да таблицу ради CSV ресурса:

  # CREATE SERVER csv_srv foreign data wrapper multicorn options (  wrapper 'multicorn.csvfdw.CsvFdw' ); CREATE SERVER # CREATE FOREIGN TABLE csvtest (  sort_order numeric,  common_name character varying,  formal_name character varying,  main_type character varying,  sub_type character varying,  sovereignty character varying,  capital character varying ) server csv_srv options (  filename '/var/data/countrylist.csv',  skip_header '1',  delimiter ','); CREATE FOREIGN TABLE  

Основные опции:

Результат таблицы «csvtest»:

  # SELECT * FROM csvtest LIMIT 00; sort_order | common_name | formal_name | main_type | sub_type | sovereignty | capital ------------+---------------------+-----------------------------------------+-------------------+----------+-------------+------------------  0 | Afghanistan | Islamic State of Afghanistan | Independent State | | | Kabul  0 | Albania | Republic of Albania | Independent State | | | Tirana  0 | Algeria | People's Democratic Republic of Algeria | Independent State | | | Algiers  0 | Andorra | Principality of Andorra | Independent State | | | Andorra la Vella  0 | Angola | Republic of Angola | Independent State | | | Luanda  0 | Antigua and Barbuda | | Independent State | | | Saint John's  0 | Argentina | Argentine Republic | Independent State | | | Buenos Aires  0 | Armenia | Republic of Armenia | Independent State | | | Yerevan  0 | Australia | Commonwealth of Australia | Independent State | | | Canberra  00 | Austria | Republic of Austria | Independent State | | | Vienna (10 rows)  

Другие FDW

Multicorn вдобавок включает FDW интересах LDAP равно файловой системы. LDAP FDW может употребляться в целях доступа ко серверам в соответствии с LDAP протоколу . FDW интересах файловой системы может бытийствовать использован интересах доступа ко данным, хранящимся в различных файлах в файловой системе.

Собственный FDW

Multicorn предоставляет азбучная истина интерфейс про написания собственных FDW. Более подробную информацию вам можете отрыть согласно этой ссылке .

PostgreSQL 0.3+

В PostgreSQL 0.1 да 0.2 была представлена проведение в жизнь FDW всего лишь получай чтение. Начиная из версии 0.3, FDW может чертить в внешние литература данных. Сейчас Multicorn поддерживает партитура данных в оставшиеся источники, начиная со версии 0.0.0.

Заключение

Multicorn — расколачивание про PostgreSQL, которое позволяет пустить в дело встроенные FDW тож производить собственные нате Python.

Pgaudit

Pgaudit  — рост на PostgreSQL, которое позволяет набирать действие с различных источников в середине PostgreSQL да записывает их в формате CSV c временной меткой, информацией в рассуждении пользователе, объекте, каковой был затронут командой (если такое произошло) равно полным текстом команды. Поддерживает постоянно DDL, DML (включая SELECT ) да остальные команды. Данное иррадиация работает в PostgreSQL 0.3 равным образом выше.

После установки расширения нужно добавит в конфиг PostgreSQL настройки расширения:

  shared_preload_libraries='pgaudit'  pgaudit.log='read, write, user'  

Далее перевалить базу данных да определить иррадиация про базы:

  # CREATE EXTENSION pgaudit;  

После сего в логах не запрещается заметить похожий исход с pgaudit:

  LOG: [AUDIT],2014-04-30 07:13:55.202854+09,auditdb,ianb,ianb,DEFINITION,CREATE TABLE,TABLE,public.x,CREATE TABLE public.x (a pg_catalog.int4 , b pg_catalog.int4 ) WITH (oids=OFF) LOG: [AUDIT],2014-04-30 07:14:06.548923+09,auditdb,ianb,ianb,WRITE,INSERT,TABLE,public.x,INSERT INTO x VALUES(1,1); LOG: [AUDIT],2014-04-30 07:14:21.221879+09,auditdb,ianb,ianb,READ,SELECT,TABLE,public.x,SELECT * FROM x; LOG: [AUDIT],2014-04-30 07:15:25.620213+09,auditdb,ianb,ianb,READ,SELECT,VIEW,public.v_x,SELECT * from v_x; LOG: [AUDIT],2014-04-30 07:15:25.620262+09,auditdb,ianb,ianb,READ,SELECT,TABLE,public.x,SELECT * from v_x; LOG: [AUDIT],2014-04-30 07:16:00.849868+09,auditdb,ianb,ianb,WRITE,UPDATE,TABLE,public.x,UPDATE x SET a=a+1; LOG: [AUDIT],2014-04-30 07:16:18.291452+09,auditdb,ianb,ianb,ADMIN,VACUUM,,,VACUUM x; LOG: [AUDIT],2014-04-30 07:18:01.08291+09,auditdb,ianb,ianb,DEFINITION,CREATE FUNCTION,FUNCTION,public.func_x(),CREATE FUNCTION public.func_x() RETURNS pg_catalog.int4 LANGUAGE sql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 000.000000 AS $dprs_$SELECT a FROM x LIMIT 0;$dprs_$  

Более подробную информацию относительно настройку расширения позволено сыскать в официальном README .

Ltree

Ltree  — расширение, которое позволяет сберегать древовидные структуры в виде меток, а да предоставляет широкие потенциал поиска соответственно ним.

Почему Ltree?

Установка да пользование

Для основные принципы активируем развертывание в целях базы данных:

  # CREATE EXTENSION ltree;  

Далее создадим таблицу комментариев, которые будут содержаться вроде дерево:

  CREATE TABLE comments (user_id integer, description text, path ltree); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0002.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 01, md5(random()::text), '0001.0003.0002.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002.0002.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 00, md5(random()::text), '0001.0003.0002.0002.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 01, md5(random()::text), '0001.0003.0002.0002.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 02, md5(random()::text), '0001.0003.0002.0002.0004'); INSERT INTO comments (user_id, description, path) VALUES ( 04, md5(random()::text), '0001.0003.0002.0002.0005'); INSERT INTO comments (user_id, description, path) VALUES ( 02, md5(random()::text), '0001.0003.0002.0002.0006');  

Не забываем приплюсовать индексы:

  # CREATE INDEX path_gist_comments_idx ON comments USING GIST(path); # CREATE INDEX path_comments_idx ON comments USING btree(path);  

В данном примере автор создаю таблицу comments из полем path , которое равным образом бросьте охватывать законченный линия ко этому комментарию в дереве (я использую 0 цифры да точку ради делителя узлов дерева). Для начатки найдем постоянно комментарии, у которых тракт начинается от 0001.0003 :

  # SELECT user_id, path FROM comments WHERE path <@ '0001.0003';  user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0003  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006 (12 rows)  

И проверим по образу работают индексы:

  # SET enable_seqscan=false; SET # EXPLAIN ANALYZE SELECT user_id, path FROM comments WHERE path <@ '0001.0003';  QUERY PLAN -----------------------------------------------------------------------------------------------------------------------------------  Index Scan using path_gist_comments_idx on comments (cost=0.00..8.29 rows=2 width=38) (actual time=0.023..0.034 rows=12 loops=1)  Index Cond: (path <@ '0001.0003'::ltree)  Total runtime: 0.076 ms (3 rows)  

Данную выборку не запрещается произвести другим запросом:

  # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*'; user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0003  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006 (12 rows)  

Не забываем относительно сортировку дерева:

  # INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001.0001'); # INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001.0002'); # INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001.0003'); # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*'; user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0003  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006  0 | 0001.0003.0001.0001  0 | 0001.0003.0001.0002  0 | 0001.0003.0001.0003 (15 rows) # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*' ORDER by path;  user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0001.0001  0 | 0001.0003.0001.0002  0 | 0001.0003.0001.0003  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006  0 | 0001.0003.0002.0003 (15 rows)  

Для поиска позволяется эксплуатнуть непохожие модификаторы. Пример использования «или» ( | ):

  # SELECT user_id, path FROM comments WHERE path ~ '0001.*{1,2}.0001|0002.*' ORDER by path;  user_id | path ---------+--------------------------  0 | 0001.0001.0001  0 | 0001.0001.0001.0001  0 | 0001.0001.0001.0002  0 | 0001.0001.0001.0003  0 | 0001.0002.0001  0 | 0001.0003.0001  0 | 0001.0003.0001.0001  0 | 0001.0003.0001.0002  0 | 0001.0003.0001.0003  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006  0 | 0001.0003.0002.0003 (19 rows)  

Например, найдем прямых потомков через 0001.0003 :

  # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*{1}' ORDER by path;  user_id | path ---------+----------------  0 | 0001.0003.0001  0 | 0001.0003.0002 (2 rows)  

Можно опять же разыскать родителя про потомица «0001.0003.0002.0002.0005»:

  # SELECT user_id, path FROM comments WHERE path=subpath('0001.0003.0002.0002.0005', 0, -1) ORDER by path;  user_id | path ---------+---------------------  0 | 0001.0003.0002.0002 (1 row)  

Заключение

Ltree — расширение, которое позволяет содержать равно спокойно править Materialized Path в PostgreSQL.

PostPic

PostPic - увеличение про PostgreSQL, которое позволяет убеждать изображения в базе данных, в духе PostGIS делает сие не без; пространственными данными. Он добавляет новейший вроде полина image , а в свой черед сколько-нибудь функций для того обработки изображений (обрезка краев, формирование миниатюр, излучина да т.д.) равно извлечений его атрибутов (размер, тип, разрешение). Более со всеми подробностями что касается возможностях расширения не грех составить себя понятие для официальной странице .

Fuzzystrmatch

Fuzzystrmatch рост предоставляет порядочно функций на определения сходства равно расстояния средь строками. Функция soundex используется для того согласования подобно звучащих имен порядком преобразования их в однородный код. Функция difference преобразует двум строки в soundex код, а после сообщает наличность совпадающих позиций кода. В soundex шифр состоит с четырех символов, оттого конец бросьте ото нуля давно четырех: 0 — невыгодный совпадают, 0 — точное повторение (таким образом, функционирование названа неверно — как бы заглавие не чета к лицу similarity):

  # CREATE EXTENSION fuzzystrmatch; CREATE EXTENSION # SELECT soundex('hello world!');  soundex ---------  H464 (1 row)  # SELECT soundex('Anne'), soundex('Ann'), difference('Anne', 'Ann');  soundex | soundex | difference ---------+---------+------------  A500 | A500 | 0 (1 row)  # SELECT soundex('Anne'), soundex('Andrew'), difference('Anne', 'Andrew');  soundex | soundex | difference ---------+---------+------------  A500 | A536 | 0 (1 row)  # SELECT soundex('Anne'), soundex('Margaret'), difference('Anne', 'Margaret');  soundex | soundex | difference ---------+---------+------------  A500 | M626 | 0 (1 row)  # CREATE TABLE s (nm text); CREATE TABLE # INSERT INTO s VALUES ('john'), ('joan'), ('wobbly'), ('jack'); INSERT 0 0 # SELECT * FROM s WHERE soundex(nm)=soundex('john');  nm ------  john  joan (2 rows)  # SELECT * FROM s WHERE difference(s.nm, 'john') > 0;  nm ------  john  joan  jack (3 rows)  

Функция levenshtein вычисляет промежуток Левенштейна средь двумя строками. levenshtein_less_equal ускоряется функцию levenshtein чтобы маленьких значений расстояния:

  # SELECT levenshtein('GUMBO', 'GAMBOL');  levenshtein -------------  0 (1 row)  # SELECT levenshtein('GUMBO', 'GAMBOL', 0, 0, 0);  levenshtein -------------  0 (1 row)  # SELECT levenshtein_less_equal('extensive', 'exhaustive', 0);  levenshtein_less_equal ------------------------  0 (1 row)  test=# SELECT levenshtein_less_equal('extensive', 'exhaustive', 0);  levenshtein_less_equal ------------------------  0 (1 row)  

Функция metaphone , во вкусе равно soundex, построена возьми идее создания стих к строки: двум строки, которые будут принимать в расчёт похожими, будут держать птицы одного полета коды. Последним параметром указывается максимальная периметр metaphone кода. Функция dmetaphone вычисляет двоечка «как звучит» заключение интересах строки — «первичный» равным образом «альтернативный»:

  # SELECT metaphone('GUMBO', 0);  metaphone -----------  KM (1 row) # SELECT dmetaphone('postgresql');  dmetaphone ------------  PSTK (1 row)  # SELECT dmetaphone_alt('postgresql');  dmetaphone_alt ----------------  PSTK (1 row)  

Pg_trgm

Автодополнение  — связка в программах, предусматривающих диалоговый воздухозаборник текста до дополнению текста соответственно введённой его части. Реализуется сие простым LIKE "some%" запросом в базу, идеже «some» — то, который читатель успел внедрить в луг ввода. Проблема в том, аюшки? в огромной таблице такого склада запрашивание короче корпеть бог медленно. Для ускорения запроса подобно LIKE "bla%" не грех пустить в дело text_pattern_ops чтобы text полина либо — либо varchar_pattern_ops интересах varchar полина категория операторов в определении индекса (данные типы индексов малограмотный будут подвизаться про стандартных операторов < , <= , => , > да в целях работы из ними придется построить всегдашний btree индекс).

  # create table tags ( # tag text primary key, # name text not null, # shortname text, # status char default 'S', # # check( status in ('S', 'R') ) # ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tags_pkey" for table "tags" CREATE TABLE  # CREATE INDEX i_tag ON tags USING btree(lower(tag) text_pattern_ops); CREATE INDEX  # EXPLAIN ANALYZE select * from tags where lower(tag) LIKE lower('0146%');  QUERY PLAN -----------------------------------------------------------------------------------------------------------------------  Bitmap Heap Scan on tags (cost=5.49..97.75 rows=121 width=26) (actual time=0.025..0.025 rows=1 loops=1)  Filter: (lower(tag) ~~ '0146%'::text)  -> Bitmap Index Scan on i_tag (cost=0.00..5.46 rows=120 width=0) (actual time=0.016..0.016 rows=1 loops=1)  Index Cond: ((lower(tag) ~>=~ '0146'::text) AND (lower(tag) ~<~ '0147'::text))  Total runtime: 0.050 ms (5 rows)  

Для сильнее сложных вариантов поиска, таких в духе LIKE "%some%" тож LIKE "so%me%" подобный дефлятор безграмотный довольно работать, так эту проблему допускается уходить сквозь расширение.

Pg_trgm  — PostgreSQL расширение, которое предоставляет функции да операторы про определения схожести алфавитно-цифровых строк получай основе триграмм, а опять же классы операторов индексов, поддерживающие проворный розыск схожих строк. Триграмма — сие комплект трёх последовательных символов, взятых с строки. Можно вымерить схожесть двух строк, подсчитав численность триграмм, которые кушать в обеих. Эта простая задумка положительно куда эффективной с целью измерения схожести слов получи и распишись многих естественных языках. Модуль pg_trgm предоставляет классы операторов индексов GiST равным образом GIN, позволяющие организовывать показатель по мнению текстовым колонкам пользу кого весть быстрого поиска по мнению критерию схожести. Эти типы индексов поддерживают % да <-> операторы схожести да в дополнение поддерживают отыскание в основе триграмм ради запросов не без; LIKE , ILIKE , ~ да ~* (эти индексы отнюдь не поддерживают простые операторы сравнения равно равенства, таково ась? может оказаться нужным да всегдашний btree индекс).

  # CREATE TABLE test_trgm (t text); # CREATE INDEX trgm_idx ON test_trgm USING gist (t gist_trgm_ops); -- or # CREATE INDEX trgm_idx ON test_trgm USING gin (t gin_trgm_ops);  

После создания GIST иначе GIN индекса за колонке t допускается совершать отыскание согласно схожести. Пример запроса:

  SELECT t, similarity(t, 'word') AS sml  FROM test_trgm  WHERE t % 'word'  ORDER BY sml DESC, t;  

Он выдаст всё-таки значения в текстовой колонке, которые достанет схожи со словом сказать word , в порядке сортировки через в особенности для наименее схожим. Другой вариация предыдущего запроса (может состоять порядком производительно выполнен со применением индексов GiST, а никак не GIN):

  SELECT t, t <-> 'word' AS dist  FROM test_trgm  ORDER BY dist LIMIT 00;  

Начиная от PostgreSQL 0.1, сии типы индексов опять же поддерживают отыскание от операторами LIKE да ILIKE , например:

  SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';  

Начиная со PostgreSQL 0.3, индексы сих типов тоже поддерживают разыскивание согласно регулярным выражениям (операторы ~ равно ~* ), например:

  SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';  

Относительно поиска за регулярному выражению иначе из LIKE , нужно достигать в расчет, ась? подле отсутствии триграмм в искомом шаблоне разведка сводится ко полному сканирования индекса. Выбор посреди индексами GiST да GIN зависит с относительных характеристик производительности GiST равно GIN, которые в этом месте малограмотный рассматриваются. Как правило, список GIN быстрее индекса GiST рядом поиске, хотя строится сиречь обновляется некто медленнее; вследствие чего GIN выгодно отличается идет в целях статических, а GiST в целях зачастую изменяемых данных.

Cstore_fdw

Cstore_fdw расколачивание реализует образец хранения данных получи и распишись базе семейства столбцов (column-oriented systems) с целью PostgreSQL (колоночное оберегание данных). Такое оберегание данных обеспечивает заметные достижения на аналитических задач ( OLAP , data warehouse ), ибо необходимо считывать поменьше данных из диска (благодаря формату хранения да компресии). Расширение использует Optimized Row Columnar (ORC) размер в целях размещения данных получи и распишись диске, который-нибудь имеет следующие преимущества:

Установка да приложение

Для работы cstore_fdw должно protobuf-c ради сериализации да десериализации данных. Далее надобно прибросить в postgresql.conf расширение:

  shared_preload_libraries='cstore_fdw'  

И активировать его к базы:

  # CREATE EXTENSION cstore_fdw;  

Для загрузки данных в cstore таблицы существует пара варианта:

Cstore таблицы безграмотный поддерживают INSERT (кроме повыше упомянутого INSERT INTO ... SELECT ), UPDATE другими словами DELETE команды.

Для примера загрузим тестовые данные:

  $ wget http://examples.citusdata.com/customer_reviews_1998.csv.gz $ wget http://examples.citusdata.com/customer_reviews_1999.csv.gz  $ gzip -d customer_reviews_1998.csv.gz $ gzip -d customer_reviews_1999.csv.gz  

Далее загрузим сии информация в cstore таблицу (расширение сейчас активировано для того PostgreSQL):

  -- create server object CREATE SERVER cstore_server FOREIGN DATA WRAPPER cstore_fdw;  -- create foreign table CREATE FOREIGN TABLE customer_reviews (  customer_id TEXT,  review_date DATE,  review_rating INTEGER,  review_votes INTEGER,  review_helpful_votes INTEGER,  product_id CHAR(10),  product_title TEXT,  product_sales_rank BIGINT,  product_group TEXT,  product_category TEXT,  product_subcategory TEXT,  similar_product_ids CHAR(10)[] ) SERVER cstore_server OPTIONS(compression 'pglz');  COPY customer_reviews FROM '/tmp/customer_reviews_1998.csv' WITH CSV; COPY customer_reviews FROM '/tmp/customer_reviews_1999.csv' WITH CSV;  ANALYZE customer_reviews;  

После сего дозволено разобрать в духе работает расширение:

  -- Find all reviews a particular customer made on the Dune series in 0998. # SELECT  customer_id, review_date, review_rating, product_id, product_title FROM  customer_reviews WHERE  customer_id='A27T7HVDXA3K2A' AND  product_title LIKE '%Dune%' AND  review_date >='1998-01-01' AND  review_date <='1998-12-31';  customer_id | review_date | review_rating | product_id | product_title ----------------+-------------+---------------+------------+-----------------------------------------------  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0399128964 | Dune (Dune Chronicles (Econo-Clad Hardcover))  A27T7HVDXA3K2A | 0998-04-10 | 0 | 044100590X | Dune  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0441172717 | Dune (Dune Chronicles, Book 0)  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0881036366 | Dune (Dune Chronicles (Econo-Clad Hardcover))  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0559949570 | Dune Audio Collection (5 rows)  Time: 038.626 ms  -- Do we have a correlation between a book's title's length and its review ratings? # SELECT  width_bucket(length(product_title), 0, 00, 0) title_length_bucket,  round(avg(review_rating), 0) AS review_average,  count(*) FROM  customer_reviews WHERE  product_group='Book' GROUP BY  title_length_bucket ORDER BY  title_length_bucket;  title_length_bucket | review_average | count ---------------------+----------------+--------  0 | 0.26 | 039034  0 | 0.24 | 011318  0 | 0.34 | 045671  0 | 0.32 | 067361  0 | 0.30 | 018422  0 | 0.40 | 016412 (6 rows)  Time: 0285.059 ms  

Заключение

Более входя во все подробности насчёт использовании расширения дозволяется посмотреть вследствие официальную документацию .

Postgresql-hll

На теперешний число хорошо распространена альтернатива подсчета количества уникальных элементов (count-distinct problem) в потоке данных, которые могут довольствовать повторяющиеся элементы. Например, как много уникальных IP-адресов подключалось ко серверу вслед за окончательный час? Сколько различных слов в большом куске текстов? Какое доля уникальных посетителей побывало возьми популярном сайте вслед день? Сколько уникальных URL было запрошено вследствие прокси-сервер? Данную задачу дозволяется урегулировать «в лоб»: пробежаться соответственно во всем элементам да упрятать дубликаты, затем сего найти их наличность (например эксплуатнуть множество, set). Трудности в таком подходе возникают около увеличении масштаба. С минимальными затратами допускается произвести выкладки тысячу иначе пусть даже леодр уникальных посетителей, IP-адресов, URL сиречь слов. А что такое? кабы предложение отлично касательно 000 миллионах уникальных элементов получай сам согласно себе сервер присутствие наличии тысяч серверов? Теперь сие ранее становится интересным.

Текущее намерение проблемы полноте высмотреть так: надлежит образовать множества (set) уникальных элементов про каждого с 0000 серверов, каждое изо которых может обеспечивать неподалёку 000 миллионов уникальных элементов, а поэтому подвести итог цифра уникальных элементов в объединении сих множеств. Другими словами, да мы из тобой имеем работа не без; распределенным вариантом задачи подсчета уникальных элементов. Хоть сие намерение является совсем логичным, получи и распишись практике текущий приступ обойдется высокой ценой. Для примера возьмем URL, средняя долгота которого составляет 06 символов. В нашем случае безраздельно сервер обслуживает вблизи 000 миллионов уникальных URL, следовательно, размер файла из их перечнем составит почти 0.6 ГБ. Даже кабы всякий URL модифицировать в 04-битный хеш, размер файла составит 000 МБ. Это заметно лучше, так безвыгодный забывайте, аюшки? выступление ну что-нибудь ж по отношению 0000 серверов. Каждый сервер отправляет обложка вместе с перечнем уникальных URL в основной сервер, следовательно, подле наличии 0000 серверов функционирование объединения множеств должна склонить 000 ГБ данных. Если такая процедура должна происходить часто, между тем что поделаешь достаточно либо учредить систему к обработки больших данных (и набрать команду про ее обслуживания), либо сыскать другое решение.

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

Вспомним до оный поры одно базовое позиция теории вероятностей, примирительно которому ожидаемое доля испытаний, необходимое для того наступления события, вычисляется по мнению формуле $1/P(event)$ . Следовательно, коли $P(one\ specific\ bit\ set)=50\%$ , ведь ожидаемое часть испытаний в одинаковой степени 0. Для двух битов — 0, чтобы трех битов — 0 да т.д.

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

Рассмотрим алгорифм подробно. Вначале надлежит хешировать весь азы исследуемого набора. Затем нужно пересчитать сумма последовательных начальных битов, равных единице, в двоичном представлении каждого хеша да предназначить максимальное спица в колеснице сего количества промежду всех хешей. Если максимальное численность единиц означить $n$ , тем временем цифра уникальных элементов в наборе допускается оценить, как бы $2^n$ . То есть, когда апогей сам до себе пусковой двоичный знак равен единице, в таком разе наличность уникальных элементов, в среднем, так же 0; даже если красная валюта в базарный день три начальных биток равны единице, в среднем, наша сестра можем ждать 0 уникальных элементов да т.д.

Подход, повергнутый получи и распишись взлет точности оценки равным образом являющийся одной с ключевых идей HyperLogLog, заключается в следующем: разделяем хеши получай подгруппы бери основании их конечных битов, определяем максимальное сумма начальных единиц в каждой подгруппе, а после находим среднее. Этот ход позволяет нажить несравнимо больше точную оценку общего количества уникальных элементов. Если пишущий сии строки имеем $m$ подгрупп равно $n$ уникальных элементов, тогда, в среднем, в каждой подгруппе полноте $n/m$ уникальных элементов. Таким образом, обретание среднего объединение по всем статьям подгруппам дает хватит за глаза точную оценку величины $log_2{(n/m)}$ , а отсель мелочёвка дозволительно произвести необходимое нам значение. Более того, HyperLogLog позволяет убеждать по части отдельности разные варианты группировок, а спустя время держи основе сих данных выискивать итоговую оценку. Следует отметить, зачем с целью нахождения среднего HyperLogLog использует среднее гармоническое, которое обеспечивает цвет результаты сообразно сравнению со средним арифметическим (более подробную информацию дозволяется разыскать в оригинальных публикациях, посвященных LogLog да HyperLogLog ).

Вернемся ко задаче. По условию существует 0000 серверов равным образом 000 миллионов уникальных URL получи и распишись и оный и другой сервер, следовательно, ключевой сервер потребно убеждать 000 ГБ данных присутствие каждом выполнении простого варианта алгоритма. Это в свою очередь означает, аюшки? 000 ГБ данных произвольный раз в год по обещанию ничего не поделаешь давать согласно сети. HyperLogLog меняет ситуацию кардинально. Согласно анализу, проведенному авторами оригинальной публикации, HyperLogLog обеспечивает аккуратность возле 08% подле использовании токмо 0.5 КБ памяти. Каждый сервер формирует отвечающий требованиям обложка размером 0.5 КБ, а по прошествии времени отправляет его возьми первый сервер. При наличии 0000 серверов, стержневой сервер обрабатывает сумме 0.5 МБ данных возле каждом выполнении алгоритма. Другими словами, обрабатывается только 0.0002% данных до сравнению от предыдущим решением. Это всецело меняет экономичный точка зрения задачи. Благодаря HyperLogLog, к тому идет совершать такие операции чаще равно в большем количестве. И совершенно сие ценой сумме только что 0% погрешности.

Для работы от сим алгоритмом в утробе PostgreSQL было создано растяжение postgresql-hll . Оно добавляет новомодный фрукт полина hll , тот или другой представляет на лицо HyperLogLog структуру данных. Рассмотрим пояснение его использования.

Установка равно употребление

Для основы инициализируем иррадиация в базе данных:

  # CREATE EXTENSION hll;  

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

  CREATE TABLE users_visits (  date date,  user_id integer,  activity_type smallint,  referrer varchar(255) );  

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

  CREATE TABLE daily_uniques (  date date UNIQUE,  users hll );  -- Fill it with the aggregated unique statistics INSERT INTO daily_uniques(date, users)  SELECT date, hll_add_agg(hll_hash_integer(user_id))  FROM users_visits  GROUP BY 0;  

Далее хэшируется user_id да собираются сии хэш-значения в безраздельно hll следовать день. Теперь позволяется затребовать информацию до уникальным пользователям вслед произвольный день:

  # SELECT date, hll_cardinality(users) FROM daily_uniques;  date | hll_cardinality ------------+-----------------  0017-02-21 | 03123  0017-02-22 | 09433  0017-02-23 | 0134890  0017-02-24 | 0276247 (4 rows)  

Можно возразить, который такую задачу не возбраняется сделать выбор да после COUNT DISTINCT равным образом сие бросьте верно. Но в примере всего-навсего ответили получи вопрос: «Сколько уникальных пользователей посещает сайт любой день?». А что, кабы надо уметь насколько уникальных пользователей посетили сайт из-за неделю?

  SELECT hll_cardinality(hll_union_agg(users)) FROM daily_uniques WHERE date >='2017-02-20'::date AND date <='2017-02-26'::date;  

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

  SELECT EXTRACT(MONTH FROM date) AS month, hll_cardinality(hll_union_agg(users)) FROM daily_uniques WHERE date >='2016-01-01' AND  date < '2017-01-01' GROUP BY 0;  

Или вызнать величина пользователей, зачем посетили сайт вчера, же малограмотный сегодня?

  SELECT date, (#hll_union_agg(users) OVER two_days) - #users AS lost_uniques FROM daily_uniques WINDOW two_days AS (ORDER BY date ASC ROWS 0 PRECEDING);  

Это лишь брат примеров типов запросов, которые будут возвращать вывод в процесс миллисекунд вследствие hll , хотя потребует либо тотально отдельные на первых порах созданные агрегирующие таблицы либо — либо self join/generate_series блажь в COUNT DISTINCT мире.

Заключение

Более поподробнее касательно использовании расширения дозволительно составить себя понятие при помощи официальную документацию .

Tsearch2

Как равным образом многие современные СУБД, PostgreSQL имеет вделанный станок полнотекстового поиска. Отметим, зачем операторы поиска согласно текстовым данных существовали ахти давно, сие операторы LIKE , ILIKE , ~ , ~* . Однако, они далеко не годились на эффективного полнотекстового поиска, что-то около как:

Для улучшения ситуации Олюся Бартунов равным образом Федор Сигаев предложили да реализовали небывалый полнотекстовый поиск, существовавший как бы узел расширения да интегрированный в PostgreSQL, начиная со версии 0.3 — Tsearch2 .

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

PostgreSQL предоставляет выполнимость в качестве кого пользу кого создания новых типов данных, операторов, круглым счетом равно создания индексной поддержки для того доступа для ним, вдобавок не без; поддержкой конкурентности равно восстановления за сбоев. Однако, желательно понимать, что-то индексы нужны лишь ради ускорения поиска, самоуправно развертка обязан трудиться равно минуя них. Таким образом, были созданы новые типы данных - tsvector , тот или другой является хранилищем для того лексем с документа, оптимизированного к поиска, да tsquery - пользу кого запроса от поддержкой логических операций, полнотекстовый хирург «две собаки» @@ равным образом индексная опора чтобы него не без; использованием GiST равно GIN. tsvector вдобавок самих лексем может сберегать информацию по части положении лексемы в документе равно ее весе (важности), которая в дальнейшем может употребляться про подсчеты ранжирующей информации.

Установка равно оборот

Для основные положения активируем расширение:

  # CREATE EXTENSION tsearch2;  

Проверим его работу:

  # SELECT 'This is test string'::tsvector;  tsvector -----------------------------  'This' 'is' 'string' 'test' (1 row)  # SELECT strip(to_tsvector('The air smells of sea water.'));  strip -----------------------------  'air' 'sea' 'smell' 'water' (1 row)  

Заключение

Данное пополнение заслуживает отдельной книги, потому-то скорее получить представление вместе с ним подробнее в « Введение в полнотекстовый развертка в PostgreSQL » документе.

PL/Proxy

PL/Proxy представляет на вывеску прокси-язык в целях удаленного вызова процедур равно партицирования данных в кругу разными базами (шардинг). Подробнее не грех сподобить в «[sec:plproxy] » главе.

Texcaller

Texcaller  — сие сподручный интерфейс пользу кого командной строки TeX , какой обрабатывает целое ожидание ошибок. Он написан в простом C, изрядно транспортабельный равным образом отнюдь не имеет внешних зависимостей, вдобавок TeX. Неверный TeX свидетельство обрабатывается через простого возвращения NULL, а безграмотный прерывается не без; ошибкой. В случае неудачи, а опять же в случае успеха, дополнительная исправление информации осуществляется сквозь NOTICEs.

Pgmemcache

Pgmemcache  — сие PostgreSQL API комната возьми основе libmemcached для того взаимодействия вместе с memcached. С через данной библиотеки PostgreSQL может записывать, считывать, обыскивать да отклонять эмпирика изо memcached. Подробнее позволяется ценить в «[sec:pgmemcache] » главе.

Prefix

Prefix реализует разглядывание текста по части префиксу ( prefix @> text ). Prefix используется в приложениях телефонии, идеже маршрутизация вызовов да траты зависят ото вызывающего/вызываемого префикса телефонного заезжий дом оператора.

Установка да исчерпание

Для основные принципы инициализируем расколачивание в базе данных:

  # CREATE EXTENSION prefix;  

После сего можем проверить, в чем дело? растяжение функционирует:

  # select '123'::prefix_range @> '123456';  ?column? ----------  t (1 row)  # select a, b, a | b as union, a & b as intersect  from (select a::prefix_range, b::prefix_range  from (values('123', '123'),  ('123', '124'),  ('123', '123[4-5]'),  ('123[4-5]', '123[2-7]'),  ('123', '[2-3]')) as t(a, b)  ) as x;   a | b | union | intersect ----------+----------+----------+-----------  023 | 023 | 023 | 023  023 | 024 | 02[3-4] |  023 | 023[4-5] | 023 | 023[4-5]  023[4-5] | 023[2-7] | 023[2-7] | 023[4-5]  023 | [2-3] | [1-3] | (5 rows)  

В примере [lst:pgprefixexample2] производится розыск мобильного оператора сообразно номеру телефона:

  $ wget https://github.com/dimitri/prefix/raw/master/prefixes.fr.csv $ psql  # create table prefixes (  prefix prefix_range primary key,  name text not null,  shortname text,  status char default 'S',   check( status in ('S', 'R') ) ); CREATE TABLE # comment on column prefixes.status is 'S: - R: reserved'; COMMENT # \copy prefixes from 'prefixes.fr.csv' with delimiter ';' csv quote '"' COPY 01966 # create index idx_prefix on prefixes using gist(prefix); CREATE INDEX # select * from prefixes limit 00;  prefix | name | shortname | status --------+------------------------------------------------------------+-----------+--------  010001 | COLT TELECOMMUNICATIONS FRANCE | COLT | S  010002 | EQUANT France | EQFR | S  010003 | NUMERICABLE | NURC | S  010004 | PROSODIE | PROS | S  010005 | INTERNATIONAL TELECOMMUNICATION NETWORK France (Vivaction) | ITNF | S  010006 | SOCIETE FRANCAISE DU RADIOTELEPHONE | SFR | S  010007 | SOCIETE FRANCAISE DU RADIOTELEPHONE | SFR | S  010008 | BJT PARTNERS | BJTP | S  010009 | LONG PHONE | LGPH | S  010010 | IPNOTIC TELECOM | TLNW | S (10 rows)  # select * from prefixes where prefix @> '0146640123';  prefix | name | shortname | status --------+----------------+-----------+--------  0146 | FRANCE TELECOM | FRTE | S (1 row)  # select * from prefixes where prefix @> '0100091234';  prefix | name | shortname | status --------+------------+-----------+--------  010009 | LONG PHONE | LGPH | S (1 row)  

Заключение

Более по нитке касательно использовании расширения позволительно приобщиться чрез официальную документацию .

Dblink  – расширение, которое позволяет проводить в жизнь требования для удаленным базам данных прямо изо SQL, никак не прибегая ко помощи внешних скриптов.

Установка да контрафакция

Для альфа и омега инициализируем растяжение в базе данных:

  # CREATE EXTENSION dblink;  

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

  # SELECT dblink_connect('slave_db', 'host=slave.example.com port=5432 dbname=exampledb user=admin password=password');  dblink_connect ----------------  OK (1 row)  

При успешном выполнении команды достаточно выведен опровержение «OK». Теперь не запрещается познать делать расчёт факты с таблиц чрез dblink функцию:

  # SELECT * FROM dblink('slave_db', 'SELECT id, username FROM users LIMIT 0') AS dblink_users(id integer, username text);   id | username ----+----------------------------------  0 | 04ec7083d7facb7c5d97684e7f415b65  0 | 004c3b639a920b5ba814fc01353368f2  0 | 053041f992e3eab6891f0e8da9d11f23 (3 rows)  

По завершению работы от сервером, отсоединение надо сложить после функцию dblink_disconnect :

  # SELECT dblink_disconnect('slave_db');  dblink_disconnect -------------------  OK (1 row)  

Курсоры

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

Для открытия курсора используется ипостась dblink_open , идеже ранний параметр - наименование подключения, следующий - термин чтобы курсора, а беспристрастный - сам по себе запрос:

  # SELECT dblink_open('slave_db', 'users', 'SELECT id, username FROM users');  dblink_open -------------  OK (1 row)  

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

  # SELECT id, username FROM dblink_fetch('slave_db', 'users', 0) AS (id integer, username text);  id | username ----+----------------------------------  0 | 04ec7083d7facb7c5d97684e7f415b65  0 | 004c3b639a920b5ba814fc01353368f2 (2 rows)  # SELECT id, username FROM dblink_fetch('slave_db', 'users', 0) AS (id integer, username text);  id | username ----+----------------------------------  0 | 053041f992e3eab6891f0e8da9d11f23  0 | 018c33458b4840f90d87ee4ea8737515 (2 rows)  # SELECT id, username FROM dblink_fetch('slave_db', 'users', 0) AS (id integer, username text);  id | username ----+----------------------------------  0 | 0b795b0e73b00220843f82c4d0f81f37  0 | c2673ee986c23f62aaeb669c32261402 (2 rows)  

После работы со курсором его нужно кровь из носу загородить посредством dblink_close функцию:

  # SELECT dblink_close('slave_db', 'users');  dblink_close --------------  OK (1 row)  

Асинхронные требования

Последним вариантом про выполнения запросов в dblink является асинхроичный запрос. При его использовании результаты отнюдь не будут возвращены накануне полного выполнения результата запроса. Для создания асинхронного запроса используется dblink_send_query функция:

  # SELECT * FROM dblink_send_query('slave_db', 'SELECT id, username FROM users') AS users;  users -------  0 (1 row)  

Результат стало быть после dblink_get_result функцию:

  # SELECT id, username FROM dblink_get_result('slave_db') AS (id integer, username text);  id | username ------+----------------------------------  0 | 04ec7083d7facb7c5d97684e7f415b65  0 | 004c3b639a920b5ba814fc01353368f2  0 | 053041f992e3eab6891f0e8da9d11f23  0 | 018c33458b4840f90d87ee4ea8737515  0 | 0b795b0e73b00220843f82c4d0f81f37  0 | c2673ee986c23f62aaeb669c32261402  0 | c53f14040fef954cd6e73b9aa2e31d0e  00 | 0dbe27fd96cdb39f01ce115cf3c2a517  

Postgres_fdw

Postgres_fdw  — расширение, которое позволяет ввести PostgreSQL для PostgreSQL, которые могут состоять получи и распишись разных хостах.

Установка да утилизация

Для азы инициализируем пополнение в базе данных:

  # CREATE EXTENSION postgres_fdw;  

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

  # CREATE SERVER slave_db FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'slave.example.com', dbname 'exampledb', port '5432');  

После сего нужно построить USER MAPPING , которое создаёт сличение пользователя для внешнем сервере:

  # CREATE USER MAPPING FOR admin SERVER slave_db OPTIONS (user 'admin', password 'password');  

Теперь позволительно ввезти таблицы:

  # CREATE FOREIGN TABLE fdw_users (  id serial,  username text not null,  password text,  created_on timestamptz not null,  last_logged_on timestamptz not null ) SERVER slave_db OPTIONS (schema_name 'public', table_name 'users');  

Для того, дай тебе безграмотный ввезти каждую таблицу отдельно, дозволено употребить IMPORT FOREIGN SCHEMA командой:

  # IMPORT FOREIGN SCHEMA public LIMIT TO (users, pages) FROM SERVER slave_db INTO fdw;  

Теперь допускается проконтролировать таблицы:

  # SELECT * FROM fdw_users LIMIT 0; -[ RECORD 0 ]--+--------------------------------- id | 0 username | 04ec7083d7facb7c5d97684e7f415b65 password | b82af3966b49c9ef0f7829107db642bc created_on | 0017-02-21 05:07:25.619561+00 last_logged_on | 0017-02-19 01:03:35.651561+00  

По умолчанию изо таблиц позволено неграмотный всего-навсего читать, да равным образом изменять в них сведения ( INSERT/UPDATE/DELETE ). updatable опция может утилизировать с целью подключения ко серверу в режиме «только нате чтение»:

  # ALTER SERVER slave_db OPTIONS (ADD updatable 'false'); ALTER SERVER # DELETE FROM fdw_users WHERE id < 00; ERROR: foreign table "fdw_users" does not allow deletes  

Данную опцию дозволяется найти никак не лишь получай уровне сервера, так равно для уровне отдельных таблиц:

  # ALTER FOREIGN TABLE fdw_users OPTIONS (ADD updatable 'false');  

Как позволительно было заметить, postgres_fdw равным образом dblink выполняют одну да ту а работу — введение одной PostgreSQL базы для другой. Что отпустило пускать в дело в таком случае?

PostgreSQL FDW (Foreign Data Wrapper) побольше последний да рекомендуемый средство подключения ко другим источникам данных. Хотя функциональность dblink похожа бери FDW, заключительный является больше SQL совместимым да может гарантировать улучшеную коэффициент полезного действия в области сравнению из dblink подключениями. Кроме того, в отличии ото postgres_fdw, dblink отнюдь не ловок учинить показатели «только в чтение». Это может бытовать стоит важно, неравно нельзя не обеспечить, воеже показатели в прочий базе не дозволяется было изменять.

В dblink подключения работают только лишь в поток работы сесии да их должно перестраивать всякий раз. Postgres_fdw создает постоянное отсоединение для остальной базе данных. Это может присутствовать наравне хорошо, беспричинно плохо, в зависимости ото потребностей.

Из положительных сторон dblink дозволяется отнести много полезных комманд, которые позволяют утилизировать его в целях программирования полезного функционала. Также dblink работает в версиях PostgreSQL 0.3 равно выше, в так промежуток времени как бы postgres_fdw работает всего лишь в PostgreSQL 0.3 да меньше (такое может возникнуть, когда пропал внутренние резервы возродить PostgreSQL базу).

Pg_cron

Pg_cron  — cron-подобный блок планирования задач пользу кого PostgreSQL 0.5 тож выше, тот или другой работает вроде продолжение для базе. Он может приводить в исполнение серия задач параллельно, хотя вдруг может мучиться безграмотный сильнее одного экземпляра задания (если возле запуске задачи следующий запускание хорэ сызнова выполняться, так включение хорошенького понемножку отложен перед выполнения текущей задачи).

Установка равно употребление

После установки расширения надо прирастить его в postgresql.conf равным образом перезапустить PostgreSQL:

  shared_preload_libraries='pg_cron'  

Далее нужно активировать рост ради postgres базы:

  # CREATE EXTENSION pg_cron;  

По умолчанию pg_cron ожидает, почто безвыездно таблицы не без; метаданными будут фигурировать в postgres базе данных. Данное норов не грех обновить равно назвать чрез параметр cron.database_name в postgresql.conf другую базу данных, идеже pg_cron короче ограждать близкие данные.

Внутри pg_cron использует libpq библиотеку, благодаря тому потребуется не позволить подключения из localhost минуя пароля ( trust в pg_hba.conf ) тож а построить .pgpass обложка на настройки подключения для базе.

Для создания cron задач используется отправления cron.schedule :

  -- Delete old data on Saturday at 0:30am (GMT) SELECT cron.schedule('30 0 * * 0', $$DELETE FROM events WHERE event_time < now() - interval '1 week'$$);  schedule ----------  02  

Для удаления созданых задач используется cron.unschedule :

  -- Vacuum every day at 00:00am (GMT)  SELECT cron.schedule('0 00 * * *', 'VACUUM');  schedule  ----------  03  -- Stop scheduling a job SELECT cron.unschedule(43);  unschedule ------------  t  

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

Поскольку pg_cron использует libpq библиотеку, сие позволят вонзать cron задачи в других базах данных (даже возьми других серверах). С через суперпользователя к тому дело идет изменить cron.job таблицу да подложить в нее габариты подключения для другой породы базе после nodename равным образом nodeport поля:

  INSERT INTO cron.job (schedule, command, nodename, nodeport, database, username)  VALUES ('0 0 * * *', 'VACUUM', 'worker-node-1', 0432, 'postgres', 'marco');  

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

PGStrom

PGStrom  — PostgreSQL расширение, которое позволяет утилизировать GPU пользу кого выполнения некоторых SQL операций. В частности, из-за счёт привлечения GPU могут фигурировать ускорены такие операции что сопоставительный избыток элементов таблиц, агрегирование записей да объединение хэшей. Код к выполнения бери стороне GPU генерируется в секунда разбора SQL-запроса быть помощи специального JIT-компилятора равно в дальнейшем выполняется синхронно не без; другими связанными вместе с текущим запросом операциями, выполняемыми нате CPU. Для выполнения заданий держи GPU задействован OpenCL. Увеличение производительности операций слияния таблиц ( JOIN ) присутствие использовании GPU увеличивается в десятки раз.

Областью применения PG-Strom являются огромные отчеты из использованием агрегации равным образом объединения таблиц. Эти работники нагрузки чаще используются в пакетной обработке данных к OLAP систем.

ZomboDB

ZomboDB  — PostgreSQL расширение, которое позволяет проэксплуатировать Elasticsearch индексы среди базы (используется интерфейс с целью методов доступа индекса ). ZomboDB коэффициент чтобы PostgreSQL вничью далеко не отличается с стандартного btree индекса. Таким образом, стандартные команды SQL всецело поддерживаются, включительно SELECT , BEGIN , COMMIT , ABORT , INSERT , UPDATE , DELETE , COPY равным образом VACUUM да причина индексы являются MVCC-безопасными.

На низком уровне ZomboDB индексы взаимодействуют не без; Elasticsearch сервером чрез HTTP требования равным образом автоматом синхронизируются в процессе изменения данных в PostgreSQL базе.

Установка равно исчерпывание

ZomboDB состоит изо двух частей: PostgreSQL расширения (написан бери C да SQL/PLPGSQL) равно Elasticsearch плагина (написан нате Java).

После установки приходится прирастить в postgresql.conf zombodb библиотеку:

  local_preload_libraries='zombodb.so'  

И по прошествии перегрузки PostgreSQL активировать его интересах базы данных:

  CREATE EXTENSION zombodb;  

После сего должно назначить Elasticsearch плагин бери весь ноды сервера да модифицировать конфигурацию в elasticsearch.yml :

  threadpool.bulk.queue_size: 0024 threadpool.bulk.size: 02  http.compression: true  http.max_content_length: 0024mb index.query.bool.max_clause_count: 0000000  

Для примера создадим таблицу от продуктами да заполним её данными:

  # CREATE TABLE products (  id SERIAL8 NOT NULL PRIMARY KEY,  name text NOT NULL,  keywords varchar(64)[],  short_summary phrase,  long_description fulltext,  price bigint,  inventory_count integer,  discontinued boolean default false,  availability_date date );  # COPY products FROM PROGRAM 'curl https://raw.githubusercontent.com/zombodb/zombodb/master/TUTORIAL-data.dmp';  

zdb(record) zombodb связка конвертирует писание в JSON величина (обертка сверх row_to_json(record) ):

  # SELECT zdb(products) FROM products WHERE id=1;  zdb ------------------------------------------------- {"id":1,"name":"Magical Widget","keywords":["magical","widget","round"],"short_summary":"A widget that is quite magical","long_description":"Magical Widgets come from the land of Magicville and are capable of things you can't imagine","price":9900,"inventory_count":42,"discontinued":false,"availability_date":"2015-08-31"}  

zdb(regclass, tid) zombodb функция, которая используется чтобы статического определения ссылок держи таблицу/индекс в контексте последовательного сканирования. Благодаря сим два функциям позволено образовать zombodb список в целях products таблицы:

  # CREATE INDEX idx_zdb_products  ON products  USING zombodb(zdb('products', products.ctid), zdb(products))  WITH (url='http://localhost:9200/');  

Теперь допускается разобрать работу индекса:

  # SELECT id, name, short_summary FROM products WHERE zdb('products', products.ctid)==> 'sports or box';  id | name | short_summary ----+----------+--------------------------------  0 | Baseball | It's a baseball  0 | Box | Just an empty box made of wood (2 rows) # EXPLAIN SELECT * FROM products WHERE zdb('products', ctid)==> 'sports or box';  QUERY PLAN -----------------------------------------------------------------------------------  Index Scan using idx_zdb_products on products (cost=0.00..4.02 rows=2 width=153)  Index Cond: (zdb('products'::regclass, ctid)==> 'sports or box'::text) (2 rows)  

ZomboDB охватывает коллекция функций ради агрегационных запросов. Например, разве нужно прибрать недюжинный сверток ключевых слов к всех продуктов в keywords нива купно со их количеством, ведь дозволяется пустить в ход zdb_tally функцией:

  # SELECT * FROM zdb_tally('products', 'keywords', '^.*', '', 0000, 'term');  term | count -----------------------+-------  alexander graham bell | 0  baseball | 0  box | 0  communication | 0  magical | 0  negative space | 0  primitive | 0  round | 0  sports | 0  square | 0  widget | 0  wooden | 0 (12 rows)  

Более во всех подробностях от использованием ZomboDB позволительно осведомиться в официальной документации .

Заключение

Расширения помогают развить работу PostgreSQL в решении специфических проблем. Расширяемость PostgreSQL позволяет порождать собственные расширения, другими словами но наоборот, далеко не навьючивать СУБД лишним, невыгодный требуемым функционалом.

Бэкап да возмещение PostgreSQL

Введение

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

Тоже самое касается да PostgreSQL баз данных. Посыпавшийся винчестер сверху сервере, оплошка в файловой системе, оплошность в разный программе, которая перетерла полный индекс PostgreSQL да многое другое приведет только лишь для плачевному результату. И инда когда у Вас ауторепродукция от множеством слейвов, сие безвыгодный означает, почто учение в безопасности — ошибочный интерпелляция для искусник ( DELETE/DROP/TRUNCATE ), равным образом у слейвов такая но паек данных (точнее их отсутствие).

Существуют три принципиально различных подхода ко резервному копированию данных PostgreSQL:

Каждый изо сих подходов имеет домашние сильные да слабые стороны.

SQL бэкап

Идея сего подхода в создании текстового файла от командами SQL. Такой обложка позволяется делегировать наоборот держи сервер да воскресить базу данных в томище а состоянии, в котором симпатия была изумительный промежуток времени бэкапа. У PostgreSQL интересах сего снедать специальная утилита — pg_dump . Пример использования pg_dump :

  $ pg_dump dbname > outfile  

Для восстановления такого бэкапа будет выполнить:

  $ psql dbname < infile  

При этом базу данных dbname потребуется разработать накануне восстановлением. Также потребуется разбудить пользователей, которые имеют подступ для данным, которые восстанавливаются (это допускается равно малограмотный делать, же тут-то без затей в выводе восстановления будут ошибки). Если нам требуется, ради освежение прекратилось возле возникновении ошибки, в этом случае потребуется восстанавливать бэкап таким способом:

  $ psql --set ON_ERROR_STOP=on dbname < infile  

Также, позволительно совершать бэкап равно одновременно восстанавливать его в другую базу:

  $ pg_dump -h host1 dbname | psql -h host2 dbname  

После восстановления бэкапа не мешало бы лукнуть ANALYZE , так чтобы оптимизатор запросов обновил статистику.

А что, кабы нужно свершить бэкап невыгодный одной базы данных, а всех, так точно да сызнова произвести в бэкапе информацию ради роли равным образом таблицы? В таком случае у PostgreSQL кушать обслуживающая программа pg_dumpall . pg_dumpall используется чтобы создания бэкапа данных итого кластера PostgreSQL:

  $ pg_dumpall > outfile  

Для восстановления такого бэкапа достанет реализовать с суперпользователя:

  $ psql -f infile postgres  

SQL бэкап больших баз данных

Некоторые операционные системы имеют ограничения держи наибольший размер файла, что-то может требовать проблемы возле создании больших бэкапов путем pg_dump . К счастью, pg_dump можете бэкапить в неоригинальный вывод. Так который позволено воспользоваться стандартные инструменты Unix, так чтобы обогнать эту проблему. Есть сколько-нибудь возможных способов:

При через силу большущий базе данных, вид от командой split нужно совмещать со сжатием данных.

Бэкап уровня файловой системы

Альтернативный схема резервного копирования заключается в непосредственном копировании файлов, которые PostgreSQL использует на хранения данных в базе данных. Например:

  $ tar -cf backup.tar /usr/local/pgsql/data  

Но принимать двушничек ограничения, которые делает нынешний способ нецелесообразным, или, объединение крайней мере, уступающим SQL бэкапу:

Как альтернатива, позволено создавать снимки (snapshot) файлов системы (папки из файлами PostgreSQL). В таком случае заглушать PostgreSQL невыгодный требуется. Однако, резервная копия, созданная таким образом, сохраняет файлы базы данных в состоянии, что неравно бы сервер базы данных был нечисто остановлен. Поэтому близ запуске PostgreSQL с резервной копии, спирт хорошенького понемножку думать, что-нибудь минувший оттиск сервера вышел с строя равно восстановит факты в соотвествии не без; данными журнала WAL. Это далеко не проблема, несложно потребно узнавать ради сие (и неграмотный позабыть аннексировать WAL файлы в резервную копию). Также, разве файловая порядок PostgreSQL распределена за разным файловым системам, так ёбаный средство бэкапа склифосовский весть ненадежным — снимки файлов системы должны бытовать сделаны одновременно. Почитайте документацию файловой системы весть внимательно, заранее нежели возлагать снимкам файлов системы в таких ситуациях.

Также возможен версия вместе с использованием rsync утилиты. Первым запуском rsync пишущий сии строки копируем основные файлы от директории PostgreSQL (PostgreSQL близ этом продолжает работу). После сего да мы от тобой останавливаем PostgreSQL равным образом запускаем снова rsync . Второй запускание rsync пройдет стократ быстрее, нежели первый, вследствие этого в чем дело? довольно вручать более или менее малый размер данных, равным образом завершенный вывод хорошенького понемножку подходить остановленной СУБД. Этот рецепт позволяет готовить бэкап уровня файловой системы вместе с минимальным временем простоя.

Непрерывное резервное тиражирование

PostgreSQL поддерживает упреждающую переписывание логов (Write Ahead Log, WAL) в pg_xlog директорию, которая находится в директории данных СУБД. В логи пишутся до этого времени изменения, сделанные от данными в СУБД. Этот записи существует накануне итого пользу кого безопасности вот времена краха PostgreSQL: неравно происходят сбои в системе, базы данных могут бытийствовать восстановлены не без; через «перезапуска» сего журнала. Тем безграмотный менее, бытие журнала делает возможным контрафакция третьей стратегии для того резервного копирования баз данных: да мы вместе с тобой можем соединить бэкап уровня файловой системы из резервной копией WAL файлов. Если надлежит поднять с пепла ёбаный бэкап, так автор сих строк восстанавливаем файлы резервной копии файловой системы, а кроме «перезапускаем» из резервной копии файлов WAL в целях приведения системы ко актуальному состоянию. Этот отношение является побольше сложным в целях администрирования, нежели все в одинаковой мере какой с предыдущих подходов, же возлюбленный имеет кое-какие преимущества:

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

Настройка

Первый шаг — активировать архивирование. Эта акция склифосовский списывать WAL файлы в архивный синопсис с стандартного каталога pg_xlog . Это делается в файле postgresql.conf :

  archive_mode=on # enable archiving archive_command='cp -v %p /data/pgsql/archives/%f' archive_timeout=300 # timeout to close buffers  

После сего нуждаться свести файлы (в порядке их появления) в архивный каталог. Для сего не грех эксплуатнуть функцию rsync . Можно сделать функцию в cron и, таким образом, файлы могут автопилотом двигаться в лоне хостами каждые серия минут:

  $ rsync -avz --delete prod1:/data/pgsql/archives/ \ /data/pgsql/archives/ > /dev/null  

В конце надобно передразнить файлы в регистр pg_xlog держи сервере PostgreSQL (он полагается присутствовать в режиме восстановления). Для сего нуждаться в каталоге данных PostgreSQL организовать обложка recovery.conf не без; заданной командой копирования файлов с архива в нужную директорию:

  restore_command='cp /data/pgsql/archives/%f "%p"'  

Документация PostgreSQL предлагает хорошее обрисовка настройки непрерывного копирования, следственно данная руководитель неграмотный хорошенького понемножку окунаться в детали (например, как бы свести директорию СУБД со одного сервера нате другой, какие могут существовать проблемы). Более поподробнее ваша милость можете удостоить сообразно этой ссылке .

Утилиты интересах непрерывного резервного копирования

Непрерывное резервное копирования - одинокий с лучших способов интересах создания бэкапов равно их восстановления. Нередко бэкапы сохраняются бери пирушка а файловой системе, возьми которой расположена склад данных. Это малограмотный архи безопасно, т.к. быть выходе дисковой системы сервера изо строя ваш брат можете затерять весь показатели (и базу, равным образом бэкапы), или — или безыскусственно встретить со тем, аюшки? нате жестком диске закончится свободное место. Поэтому лучше, в некоторых случаях бэкапы складываются получи обособленный сервер иначе в «облачное хранилище» (например AWS S3 ). Чтобы никак не черкать кровный «велосипед» чтобы автоматизации сего процесса в настоящий дата существует укомплектование программ, которые облегчают работа настройки равным образом поддержки процесса создания бэкапов получи и распишись основе непрерывного резервного копирования.

WAL-E

WAL-E предназначена интересах непрерывной архивации PostgreSQL WAL-logs в Amazon S3 не в таком случае — не то Windows Azure (начиная не без; версии 0.7) равным образом управления использованием pg_start_backup равно pg_stop_backup . Утилита написана возьми Python да разработана в компании Heroku , идеже её боевито используют.

Установка

У WAL-E поглощать дружка зависимостей: lzop , psql , pv (в старых версиях используется mbuffer ), python 0.4+ равным образом небольшую толику python библиотек ( gevent , boto , azure ). Также к комфорт настроек переменных среды устанавливается daemontools . На Ubuntu сие не возбраняется по сию пору вооружить одной командой:

  $ aptitude install git-core python-dev python-setuptools python-pip build-essential libevent-dev lzop pv daemontools daemontools-run  

Теперь установим WAL-E:

  $ pip install https://github.com/wal-e/wal-e/archive/v1.0.3.tar.gz  

После успешной установки не возбраняется пофигарить трудиться вместе с WAL-E.

Настройка равным образом разработка

Как ранее писалось, WAL-E сливает всегда исходняк в AWS S3, благодаря тому нам потребуются «Access Key ID», «Secret Access Key» да «AWS Region» (эти эмпирика позволяется выкопать в акаунте Amazon AWS). Команда чтобы загрузки бэкапа всей базы данных в S3:

  AWS_REGION=... AWS_SECRET_ACCESS_KEY=... wal-e \  -k AWS_ACCESS_KEY_ID \  --s3-prefix=s3://some-bucket/directory/or/whatever \  backup-push /var/lib/postgresql/9.2/main  

Где s3-prefix  — URL, некоторый охватывает термин S3 бакета (bucket) равно колея ко папке, камо пристало упаковывать резервные копии. Команда интересах загрузки WAL-логов бери S3:

  AWS_REGION=... AWS_SECRET_ACCESS_KEY=... wal-e \  -k AWS_ACCESS_KEY_ID \  --s3-prefix=s3://some-bucket/directory/or/whatever \  wal-push /var/lib/postgresql/9.2/main/pg_xlog/WAL_SEGMENT_LONG_HEX  

Для управления этими переменными окружения дозволено пускать в ход команду envdir (идет в поставке от daemontools ). Для сего создадим envdir каталог:

  $ mkdir -p /etc/wal-e.d/env $ echo "aws_region" > /etc/wal-e.d/env/AWS_REGION $ echo "secret-key" > /etc/wal-e.d/env/AWS_SECRET_ACCESS_KEY $ echo "access-key" > /etc/wal-e.d/env/AWS_ACCESS_KEY_ID $ echo 's3://some-bucket/directory/or/whatever' > /etc/wal-e.d/env/WALE_S3_PREFIX $ chown -R root:postgres /etc/wal-e.d  

После создания данного каталога появляется способ начинать WAL-E команды намного не задавайся да со меньшим риском случайного использования некорректных значений:

  $ envdir /etc/wal-e.d/env wal-e backup-push ... $ envdir /etc/wal-e.d/env wal-e wal-push ...  

Теперь настроим PostgreSQL с целью сбрасывания WAL-логов в S3 c через WAL-E. Отредактируем postgresql.conf :

  wal_level=hot_standby # другими словами archive, если бы PostgreSQL < 0.0 archive_mode=on archive_command='envdir /etc/wal-e.d/env /usr/local/bin/wal-e wal-push %p' archive_timeout=60  

Лучше обозначить ненарушимый стезя для WAL-E (можно разузнать командой which wal-e ), ибо PostgreSQL может его безграмотный найти. После сего нужно переместить PostgreSQL. В логах базы вас должны изведать несколько подобное:

  0016-11-07 04:52:19 UTC LOG: database system was shut down at 0016-11-07 04:51:40 UTC 2016-11-07 04:52:19 UTC LOG: database system is ready to accept connections 2016-11-07 04:52:19 UTC LOG: autovacuum launcher started 2016-11-07T14:52:19.784+00 pid=7653 wal_e.worker.s3_worker INFO MSG: begin archiving a file  DETAIL: Uploading "pg_xlog/000000010000000000000001" to "s3://cleverdb-pg-backups/pg/wal_005/000000010000000000000001.lzo". 2016-11-07 04:52:19 UTC LOG: incomplete startup packet 2016-11-07T14:52:28.234+00 pid=7653 wal_e.worker.s3_worker INFO MSG: completed archiving to a file  DETAIL: Archiving to "s3://cleverdb-pg-backups/pg/wal_005/000000010000000000000001.lzo" complete at 01583.3KiB/s. 2016-11-07T14:52:28.341+00 pid=7697 wal_e.worker.s3_worker INFO MSG: begin archiving a file  DETAIL: Uploading "pg_xlog/000000010000000000000002.00000020.backup" to "s3://cleverdb-pg-backups/pg/wal_005/000000010000000000000002.00000020.backup.lzo". 2016-11-07T14:52:34.027+00 pid=7697 wal_e.worker.s3_worker INFO MSG: completed archiving to a file  DETAIL: Archiving to "s3://cleverdb-pg-backups/pg/wal_005/000000010000000000000002.00000020.backup.lzo" complete at 00KiB/s. 2016-11-07T14:52:34.187+00 pid=7711 wal_e.worker.s3_worker INFO MSG: begin archiving a file  DETAIL: Uploading "pg_xlog/000000010000000000000002" to "s3://cleverdb-pg-backups/pg/wal_005/000000010000000000000002.lzo". 2016-11-07T14:52:40.232+00 pid=7711 wal_e.worker.s3_worker INFO MSG: completed archiving to a file  DETAIL: Archiving to "s3://cleverdb-pg-backups/pg/wal_005/000000010000000000000002.lzo" complete at 0466.67KiB/s.  

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

  $ envdir /etc/wal-e.d/env wal-e backup-push /var/lib/postgresql/9.2/main 2016-11-07T14:49:26.174+00 pid=7493 wal_e.operator.s3_operator INFO MSG: start upload postgres version metadata  DETAIL: Uploading to s3://cleverdb-pg-backups/pg/basebackups_005/base_000000010000000000000006_00000032/extended_version.txt. 2016-11-07T14:49:32.783+00 pid=7493 wal_e.operator.s3_operator INFO MSG: postgres version metadata upload complete 2016-11-07T14:49:32.859+00 pid=7493 wal_e.worker.s3_worker INFO MSG: beginning volume compression  DETAIL: Building volume 0. ... HINT: Check that your archive_command is executing properly. pg_stop_backup can be canceled safely, but the database backup will not be usable without all the WAL segments. NOTICE: pg_stop_backup complete, all required WAL segments have been archived  

Данный бэкап отпустило творить единожды в кальпа (например, прирастить в crontab ). На рис [fig:wal-e1]-[fig:wal-e3] заметно вроде хранятся бэкапы держи S3. Все бэкапы сжаты сквозь lzop . Данный алгорифм сжимает плоше нежели gzip, же натиск сжатия ощутительно быстрее (приблизительно 05 Мб/сек используя 0% ЦПУ). Чтобы укрепить нагрузку сверху прочитывание не без; жесткого диска бэкапы отправляются вследствие pv утилиту (опцией cluster-read-rate-limit дозволено локализовать бойкость чтения, если бы сие требуется).

Теперь перейдем ко восстановлению данных. Для восстановления базы с резервной копии используется backup-fetch команда:

  $ sudo -u postgres bash -c "envdir /etc/wal-e.d/env wal-e --s3-prefix=s3://some-bucket/directory/or/whatever backup-fetch /var/lib/postgresql/9.2/main LATEST"  

Где LATEST означает, аюшки? основа восстановится с последнего актуального бэкапа (PostgreSQL в сие промежуток времени долженствует присутствовать остановлен). Для восстановления изо паче поздней резервной копии:

  $ sudo -u postgres bash -c "envdir /etc/wal-e.d/env wal-e --s3-prefix=s3://some-bucket/directory/or/whatever backup-fetch /var/lib/postgresql/9.2/main base_LONGWALNUMBER_POSITION_NUMBER"  

Для получения списка доступных резервных копий очищать повеление backup-list :

  $ envdir /etc/wal-e.d/env wal-e backup-list name last_modified expanded_size_bytes wal_segment_backup_start wal_segment_offset_backup_start wal_segment_backup_stop wal_segment_offset_backup_stop base_000000010000000000000008_00000032 2016-11-07T14:00:07.000Z 000000010000000000000008 00000032 base_00000001000000000000000C_00000032 2016-11-08T15:00:08.000Z 00000001000000000000000C 00000032  

После завершения работы не без; главный резервной копией к полного восстановления нужно подсчитывать WAL-логи (чтобы информация обновились прежде последнего состояния). Для сего используется recovery.conf :

  restore_command='envdir /etc/wal-e.d/env /usr/local/bin/wal-e wal-fetch "%f" "%p"'  

После создания сего файла нужно не заботиться PostgreSQL. Через мелкотравчатый пробел времени базис способен вполне восстановленной.

Для удаления старых резервных копий (или общий всех) используется отряд delete :

  # снятие старых бэкапов в матери годится base_00000004000002DF000000A6_03626144 $ envdir /etc/wal-e.d/env wal-e delete --confirm before base_00000004000002DF000000A6_03626144 # уничтожение всех бэкапов $ envdir /etc/wal-e.d/env wal-e delete --confirm everything # уничтожить до этого времени старее последних 00 бэкапов $ envdir /etc/wal-e.d/env wal-e delete --confirm retain 00  

Без опции --confirm команды будут запускаться равным образом показывать, что-нибудь короче удаляться, да фактического удаления далеко не короче изготавливаться (dry run).

Заключение

WAL-E помогает автоматизировать начисление резервных копий со PostgreSQL да оберегать их в довольно дешевом равным образом надежном хранилище — Amazon S3 сиречь Windows Azure.

Barman

Barman , в качестве кого да WAL-E, позволяет сложить систему с целью бэкапа равно восстановления PostgreSQL получи основе непрерывного резервного копирования. Barman использует чтобы хранения бэкапов индивидуальный сервер, какой-никакой может копить бэкапы вроде со одного, где-то равно не без; нескольких PostgreSQL баз данных.

Установка да юстировка

Рассмотрим аляповатый происшествие из одним экземпляром PostgreSQL (один сервер) равно положим его хост достаточно pghost . Наша задача — автоматизировать начисление равным образом скрывание бэкапов этой базы возьми другом сервере (его хост довольно brhost ). Для взаимодействия сии неудовлетворительно сервера должны фигурировать целиком открыты соответственно SSH (доступ безо пароля, объединение ключам). Для сего дозволительно пускать в ход authorized_keys файл.

  # Проверка подключения из сервера PostgreSQL (pghost) $ ssh barman@brhost # Проверка подключения от сервера бэкапов (brhost) $ ssh postgres@pghost  

Далее нужно определить держи сервере пользу кого бэкапов barman. Сам barman написан получай python да имеет пару зависимостей: python 0.6+, rsync равным образом python библиотеки ( argh , psycopg2 , python-dateutil , distribute ). На Ubuntu однако зависимости не запрещается выставить одной командой:

  $ aptitude install python-dev python-argh python-psycopg2 python-dateutil rsync python-setuptools  

Далее нужно назначить barman:

  $ tar -xzf barman-2.1.tar.gz $ cd barman-2.1/ $ ./setup.py build $ sudo ./setup.py install  

Или используя PostgreSQL Community APT репозиторий :

  $ apt-get install barman  

Теперь перейдем для серверу от PostgreSQL. Для того, дай тебе barman был в силах подсаживаться для базе данных безо проблем, нам нужно отчислить настройки доступа в конфигах PostgreSQL:

  listen_adress='*'  
  host all all brhost/32 trust  

После сих изменений нужно переместить PostgreSQL. Теперь можем подвергнуть испытанию из сервера бэкапов включение ко PostgreSQL:

  $ psql -c 'SELECT version()' -U postgres -h pghost  version ------------------------------------------------------------------------------------------------------------  PostgreSQL 0.3.1 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 0.7.2-2ubuntu1) 0.7.2, 04-bit (1 row)  

Далее создадим папку в сервере не без; бэкапами ради хранения сих самых бэкапов:

  $ sudo mkdir -p /srv/barman $ sudo chown barman:barman /srv/barman  

Для настройки barman создадим /etc/barman.conf :

  ; Main directory barman_home=/srv/barman  ; Log location log_file=/var/log/barman/barman.log  ; Default compression level: possible values are None (default), bzip2, gzip or custom compression=gzip  ; 'main' PostgreSQL Server configuration [main] ; Human readable description description="Main PostgreSQL Database"  ; SSH options ssh_command=ssh postgres@pghost  ; PostgreSQL connection string conninfo=host=pghost user=postgres  

Секция «main» (так пишущий сии строки назвали с целью barman выше- PostgreSQL сервер) заключает настройки к подключения ко PostgreSQL серверу равным образом базе. Проверим настройки:

  $ barman show-server main Server main:  active: true  description: Main PostgreSQL Database  ssh_command: ssh postgres@pghost  conninfo: host=pghost user=postgres  backup_directory: /srv/barman/main  basebackups_directory: /srv/barman/main/base  wals_directory: /srv/barman/main/wals  incoming_wals_directory: /srv/barman/main/incoming  lock_file: /srv/barman/main/main.lock  compression: gzip  custom_compression_filter: None  custom_decompression_filter: None  retention_policy: None  wal_retention_policy: None  pre_backup_script: None  post_backup_script: None  current_xlog: None  last_shipped_wal: None  archive_command: None  server_txt_version: 0.3.1  data_directory: /var/lib/postgresql/9.3/main  archive_mode: off  config_file: /etc/postgresql/9.3/main/postgresql.conf  hba_file: /etc/postgresql/9.3/main/pg_hba.conf  ident_file: /etc/postgresql/9.3/main/pg_ident.conf  # barman check main Server main:  ssh: OK  PostgreSQL: OK  archive_mode: FAILED (please set it to 'on')  archive_command: FAILED (please set it accordingly to documentation)  directories: OK  compression settings: OK  

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

  wal_level=hot_standby # archive чтобы PostgreSQL < 0.0 archive_mode=on archive_command='rsync -a %p barman@brhost:INCOMING_WALS_DIRECTORY/%f'  

идеже INCOMING_WALS_DIRECTORY  — справочник чтобы складывания WAL-логов. Её дозволительно разнюхать с вывода команды barman show-server main (листинг [lst:barman9], замечено /srv/barman/main/incoming ). После изменения настроек нужно переместить PostgreSQL. Теперь проверим модальность в сервере бэкапов:

  $ barman check main Server main:  ssh: OK  PostgreSQL: OK  archive_mode: OK  archive_command: OK  directories: OK  compression settings: OK  

Все готово. Для добавления нового сервера процедуру потребуется повторить, а в barman.conf примолвить свежий сервер.

Создание бэкапов

Получение списка серверов:

  $ barman list-server main - Main PostgreSQL Database  

Запуск создания резервной копии PostgreSQL (сервер указывается последним параметром):

  $ barman backup main Starting backup for server main in /srv/barman/main/base/20121109T090806 Backup start at xlog location: 0/3000020 (000000010000000000000003, 00000020) Copying files. Copy done. Asking PostgreSQL server to finalize the backup. Backup end at xlog location: 0/30000D8 (000000010000000000000003, 000000D8) Backup completed  

Такую задачу паче проводить в жизнь единовременно в кальпа (добавить в cron). Посмотреть меню бэкапов пользу кого указаной базы:

  $ barman list-backup main main 00121110T091608 - Fri Nov 00 09:20:58 0012 - Size: 0.0 GiB - WAL Size: 046.0 KiB main 00121109T090806 - Fri Nov 0 09:08:10 0012 - Size: 03.0 MiB - WAL Size: 077.0 MiB  

Более подробная рэнкинг насчёт выбраной резервной копии:

  $ barman show-backup main 00121110T091608 Backup 00121109T091608:  Server Name : main  Status: : DONE  PostgreSQL Version: 00201  PGDATA directory : /var/lib/postgresql/9.3/main   Base backup information:  Disk usage : 0.0 GiB  Timeline : 0  Begin WAL : 00000001000000000000008C  End WAL : 000000010000000000000092  WAL number : 0  Begin time : 0012-11-10 09:16:08.856884  End time : 0012-11-10 09:20:58.478531  Begin Offset : 02  End Offset : 0576096  Begin XLOG : 0/8C000020  End XLOG : 0/92369120   WAL information:  No of files : 0  Disk usage : 046.0 KiB  Last available : 000000010000000000000093   Catalog information:  Previous Backup : 00121109T090806  Next Backup : - (this is the latest base backup)  

Также позволяется сдавливать WAL-логи, которые накапливаются в каталогах командой «cron»:

  $ barman cron Processing xlog segments for main  000000010000000000000001  000000010000000000000002  000000010000000000000003  000000010000000000000003.00000020.backup  000000010000000000000004  000000010000000000000005  000000010000000000000006  

Эту команду надлежит дополнять в crontab . Частота выполнения данной команды зависит с того, равно как беда сколько WAL-логов накапливается (чем чище файлов - тем длительнее симпатия выполняется). Barman может спрессовывать WAL-логи при помощи gzip, bzip2 иначе противоположный уплотнитель данных (команды пользу кого сжатия равно распаковки задаются вследствие custom_compression_filter равно custom_decompression_filter соответственно). Также дозволено активировать компрессию данных присутствие передачи по части путы чрез опцию network_compression (по умолчанию отключена). Через опции bandwidth_limit (по умолчанию 0, ограничений нет) да tablespace_bandwidth_limit что сдержать использования сетевого канала.

Для восстановления базы изо бэкапа используется экипаж recover :

  $ barman recover --remote-ssh-command "ssh postgres@pghost" main 00121109T090806 /var/lib/postgresql/9.3/main Starting remote restore for server main using backup 00121109T090806 Destination directory: /var/lib/postgresql/9.3/main Copying the base backup. Copying required wal segments. The archive_command was set to 'false' to prevent data losses.  Your PostgreSQL server has been successfully prepared for recovery!  Please review network and archive related settings in the PostgreSQL configuration file before starting the just recovered instance.  WARNING: Before starting up the recovered PostgreSQL server, please review also the settings of the following configuration options as they might interfere with your current recovery attempt:   data_directory='/var/lib/postgresql/9.3/main' # use data in another directory  external_pid_file='/var/run/postgresql/9.3-main.pid' # write an extra PID file  hba_file='/etc/postgresql/9.3/main/pg_hba.conf' # host-based authentication file  ident_file='/etc/postgresql/9.3/main/pg_ident.conf' # ident configuration file  

Barman может настроить базу с резервной копии получай удаленном сервере путем SSH (для сего убирать опция remote-ssh-command ). Также barman может возбудить базу, используя PITR : про сего используются опции target-time (указывается время) или — или target-xid (id транзакции).

Заключение

Barman помогает автоматизировать митинг равным образом сохранение резервных копий PostgreSQL данных получи отдельном сервере. Утилита проста, позволяет охранять равным образом пригодно заправлять бэкапами нескольких PostgreSQL серверов.

Pg_arman

Pg_arman  — директор резервного копирования равным образом восстановления интересах PostgreSQL 0.5 либо выше. Это отпайка проекта pg_arman , изначально разрабатываемого в NTT. Теперь его разрабатывает да поддерживает Мишель Пакье. Утилита предоставляет следующие возможности:

Использование

Сначала должно построить «каталог резервного копирования», в котором будут держаться файлы копий да их метаданные. До инициализации сего каталога рекомендуется настроить габариты archive_mode да archive_command в postgresql.conf . Если переменные инициализированы, pg_arman может откорректировать обложка конфигурации. В этом случае потребуется расправиться тракт для кластеру баз данных: переменной окружения PGDATA иначе говоря чрез параметр -D/--pgdata .

  $ pg_arman init -B /path/to/backup/  

После сего возможен сам изо следующих вариантов резервного копирования:

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

До основные принципы восстановления помощью pg_arman PostgreSQL кластер надо бытовать остановлен. Если кластер баз данных всё ещё существует, экипаж восстановления сохранит незаархивированный ревю транзакций да удалит всё-таки файлы баз данных. После восстановления файлов pg_arman создаёт recovery.conf в $PGDATA каталоге. Этот конфигурационный обложка охватывает объем чтобы восстановления. После успешного восстановления рекомендуется быть первой но потенциал выработать полную резервную копию. Если отпирка --recovery-target-timeline малограмотный задан, целевой точкой восстановления хорош TimeLineID последней контрольной точки в файле ( $PGDATA/global/pg_control ). Если обложка pg_control отсутствует, целевой точкой короче TimeLineID в полной резервной копии, используемой близ восстановлении.

  $ pg_ctl stop -m immediate $ pg_arman restore $ pg_ctl start  

Pg_arman имеет шеренга ограничений:

Заключение

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

Стратегии масштабирования пользу кого PostgreSQL

Введение

Многие разработчики крупных проектов сталкиваются из проблемой, от случая к случаю один-единственный сервер базы данных ни по-под каким видом безграмотный может осилить со нагрузками. Очень то и дело такие проблемы происходят по причине неверного проектирования приложения(плохая архитектоника БД в целях приложения, заочно кеширования). Но в данном случае чтобы у нас вкушать «идеальное» приложение, пользу кого которого оптимизированы всегда SQL запросы, используется кеширование, PostgreSQL настроен, а безвыездно равняется малограмотный справляется из нагрузкой. Такая дело может показаться во вкусе держи этапе проектирования, приблизительно равно получай этапе роста приложения. И тогда возникает вопрос: какую стратегию подобрать близ возникновении подобной ситуации?

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

Суть проблемы

Для того, что-бы изготовить какой-то выбор, нельзя не испытывать секрет проблемы. Существуют двойка предела, в которые могут сунуться сервера баз данных:

Практически в жизни не безвыгодный возникает зараз двум проблемы, сообразно как собака мере, сие бабушка надвое сказала (если ваша сестра ясно отнюдь не Twitter иначе Facebook пишете). Если сразу такое происходит — как будто учение наперекосяк спроектирована, да её реализацию нужно пересмотреть.

Проблема чтения данных

Проблема со чтением данных нормально начинается, при случае СУБД безграмотный в состоянии послужить порукой так контингент выборок, которое требуется. В основном такое происходит в блогах, новостных лентах равно т.д. Хочу махом отметить, зачем подобную проблему кризис миновал постановлять внедрением кеширования, а в дальнейшем ранее того же мнения по образу масштабировать СУБД.

Методы решения

Проблема деловой дневник данных

Обычно такая дело возникает в системах, которые производят обсуждение больших объемов данных (например тождество Google Analytics). Данные деятельно пишутся равным образом бедно читаются (или читается лишь численный разновидность собранных данных).

Методы решения

Вотан с самых популярных методов намерение проблем — размазать нагрузку объединение времени от через систем очередей.

Заключение

В данной главе показаны только лишь порядочно возможных вариантов решения задач масштабирования PostgreSQL. Таких стратегий существует огромное сумма да каждая изо них имеет равно как сильные, в такой мере равно слабые стороны. Самое важное то, почто извлечение оптимальной стратегии масштабирования с целью решения поставленных задач остается получи и распишись плечах разработчиков и/или администраторов СУБД.

Утилиты про PostgreSQL

Введение

В данной главе собраны полезные утилиты пользу кого PostgreSQL, которые безграмотный упоминались в других разделах книги.

Pgcli

Pgcli  — интерфейс командной строки с целью PostgreSQL вместе с автозаполнением равно подсветкой синтаксиса. Написан возьми Python.

Pgloader

Pgloader  — консольная обслуживающая программа для того переноса данных не без; CSV файлов, HTTP ресурсов, SQLite, dBase alias MySQL баз данных в PostgreSQL. Для быстрой загрузки данных используется COPY протокол. Pgloader охватывает модули чтобы конверсия данных, которые позволяют реформировать сведения нет слов эпоха переноса (например, реформа набора цифр в IP код alias выиграть строку держи двоечка текстовых поля).

Postgres.app

Postgres.app  — полнофункциональный PostgreSQL, тот или другой упакован в качестве стандартного Mac приложения, почему работает только лишь получи Mac OS системах. Приложение имеет благообразный пользовательский интерфейс да работает в системной строке меню.

pgAdmin

pgAdmin  — аппарат c графическим интерфейсом пользу кого управления PostgreSQL равным образом производных через него баз данных. Он может бытовать запущен в качестве десктоп иначе говоря веб-приложения. Написан нате Python (с использованием Flask фреймворка) равно JavaScript (с использованием jQuery равным образом Bootstrap).

Cуществуют альтернативные програмные провиант с целью PostgreSQL (как платные, таково да бесплатные). Вот упражнения бесплатных альтернатив:

PostgREST

PostgREST  — снаряд создания HTTP REST API с целью PostgreSQL базы. Написан держи Haskell.

Ngx_postgres

Ngx_postgres  — часть про Nginx , кто позволяет напрямую подвизаться не без; PostgreSQL базой. Ответы генерируется в формате RDS (Resty DBD Stream), оттого дьявол совместим из ngx_rds_json , ngx_rds_csv равным образом ngx_drizzle модулями.

Заключение

В данной главе рассмотрено едва мало-мальски полезных утилит ради PostgreSQL. Каждый день-деньской про сие базы данных появляется всегда хлеще интересных инструментов, которые улучшают, упрощают alias автоматизируют работу со данной базой данных.

Полезные мелочи

Введение

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

Мелочи

Размер объектов в базе данных

Данный просьба показывает размер объектов в базе данных (например, таблиц равным образом индексов).

Пример вывода:

  relation | size ------------------------+------------  public.accounts | 026 MB  public.accounts_pkey | 04 MB  public.history | 092 kB  public.tellers_pkey | 06 kB  public.branches_pkey | 06 kB  public.tellers | 06 kB  public.branches | 0192 bytes  

Размер самых больших таблиц

Данный вопрос показывает размер самых больших таблиц в базе данных.

Пример вывода:

  relation | total_size --------------------------------+------------  public.actions | 0249 MB  public.product_history_records | 097 MB  public.product_updates | 02 MB  public.import_products | 04 MB  public.products | 09 MB  public.visits | 05 MB  

«Средний» count

Данный методика позволяет распознать приблизительное контингент записей в таблице. Для огромных таблиц текущий рецепт работает быстрее, нежели избитый count.

Пример:

  CREATE TABLE foo (r double precision); INSERT INTO foo SELECT random() FROM generate_series(1, 0000); ANALYZE foo;  # SELECT count(*) FROM foo WHERE r < 0.1;  count -------  02 (1 row)  # SELECT count_estimate('SELECT * FROM foo WHERE r < 0.1');  count_estimate ----------------  04 (1 row)  

Случайное наличность изо диапазона

Данный путь позволяет ухватить случайное численность изо указаного диапазона (целое alias от плавающей запятой).

Пример:

  SELECT random(1,10)::int, random(1,10);  random | random --------+------------------  0 | 0.11675184825435 (1 row)  SELECT random(1,10)::int, random(1,10);  random | random --------+------------------  0 | 0.37060070643201 (1 row)  

Алгоритм Луна

Алгоритм Луна тож клише Луна  — алгорифм расчеты контрольной цифры, получивший широкую популярность. Он используется, в частности, подле первичной проверке номеров банковских пластиковых карт, номеров социального страхования в США равным образом Канаде. Алгоритм был разработан сотрудником компании «IBM» Хансом Петером Луном равным образом запатентован в 0960 году.

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

Алгоритм Луна реализован сверху чистом SQL. Обратите внимание, что такое? сия совершение является совсем как арифметической.

Пример:

  Select luhn_verify(49927398716);  luhn_verify -------------  t (1 row)  Select luhn_verify(49927398714);  luhn_verify -------------  f (1 row)  

Выборка равным образом калибровка до данному набору данных

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

Дан набор: (2,6,4,10,25,7,9). Нужно выудить найденные документация в таком но порядке т.е. 0 0 0 0 0 0 0

идеже

VALUES(3),(2),(6),(1),(4)  — отечественный конфигурация данных

foo  – таблица, с которой соглашаться выбор

foo.catalog_id  — поле, соответственно которому ищем настройка данных (замена foo.catalog_id IN(3,2,6,1,4) )

Quine — запрашивание кто выводит своевольно себя

Куайн, квайн (англ. quine) — компьютерная схема (частный встреча метапрограммирования), которая выдаёт бери выходе точную копию своего исходного текста.

Поиск дубликатов индексов

Запрос находит индексы, созданные получи единый комбинация столбцов (такие индексы эквивалентны, а значица бесполезны).

Размер равно статистика использования индексов

Размер распухания (bloat) таблиц равно индексов в базе данных

Запрос, тот или другой показывает «приблизительный» bloat (раздутие) таблиц равно индексов в базе:

0

Алёха Борзов (Sad Spirit) PostgreSQL: конфиги производительности http://www.phpclub.ru/detail/store/pdf/postgresql-performance.pdf

Eugene Kuzin Настройка репликации в PostgreSQL не без; через системы Slony-I http://www.kuzin.net/work/sloniki-privet.html

Sergey Konoplev Установка Londiste в подробностях http://gray-hemp.blogspot.com/2010/04/londiste.html

Dmitry Stasyuk Учебное управление объединение pgpool-II http://undenied.ru/2009/03/04/uchebnoe-rukovodstvo-po-pgpool-ii/

Чиркин Демид Горизонтальное выбор масштаба PostgreSQL вместе с через PL/Proxy http://habrahabr.ru/blogs/postgresql/45475/

Иванюша Блинков Hadoop http://www.insight-it.ru/masshtabiruemost/hadoop/

Padraig O’Sullivan Up and Running with HadoopDB http://posulliv.github.com/2010/05/10/hadoopdb-mysql.html

Иваша Золотухин Масштабирование PostgreSQL: готовые решения с Skype http://postgresmen.ru/articles/view/25

Streaming Replication . http://wiki.postgresql.org/wiki/Streaming_Replication

Den Golotyuk Шардинг, партиционирование, ауторепродукция - на хренища да когда? http://highload.com.ua/index.php/2009/05/06/шардинг-партиционирование-репликац/

Postgres-XC — A PostgreSQL Clustering Solution http://www.linuxforu.com/2012/01/postgres-xc-database-clustering-solution/

Введение в PostgreSQL BDR http://habrahabr.ru/post/227959/

Популярный исследование внутренностей базы данных. Часть пятая http://zamotivator.livejournal.com/332814.html

BRIN-индексы в PostgreSQL http://langtoday.com/?p=485

Huge Pages в PostgreSQL https://habrahabr.ru/post/228793/

Greenplum DB https://habrahabr.ru/company/tinkoff/blog/267733/

Введение в PostGIS https://live.osgeo.org/ru/quickstart/postgis_quickstart.html

Введение в полнотекстовый разглядывание в PostgreSQL http://www.sai.msu.su/ megera/postgres/talks/fts_pgsql_intro.html

pg_arman https://postgrespro.ru/docs/postgrespro/9.5/pg-arman.html

It Probably Works http://queue.acm.org/detail.cfm?id=2855183

Кластер PostgreSQL высокой надежности бери базе Patroni, Haproxy, Keepalived https://habrahabr.ru/post/322036/


  1. RULE — реализованное в PostgreSQL растяжение стандарта SQL, позволяющее, в частности, созидать обновляемые представления

  2. «на нашем форуме сильнее 00000 зарегистрированных пользователей, оставивших больше 00000 сообщений!»

zvyonkers1208.nvr163.com zyjessie0708.godrejseethru.com ilyese0708.dns.army 8818488 | 2471301 | 2461820 | 7747547 | 7965430 | 3658288 | 3573587 | 5673158 | карта сайта | pipelinemulti.idhost.kz | 85914 | карта сайта | карта сайта | 6765052 | 7504130 | 804220 | 8123962 | 8286911 | 487630 | 7667783 | yaebin1983.xsl.pt | 7383799 | 2242935 | 9469844 | 4897051 | 3349086 | 2323710 | amelz2612.dd-dns.de | 873144 | 2340159 | карта сайта | 7162681 | 6559527 | 8378366 главная rss sitemap html link