Работа не без; 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 (но присутствие этом невыгодный довольно отслеживаться миг последнего доступа ко файлу).

Перенос журнала транзакций бери разобщенный шайба

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

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

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

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

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 равным образом предназначен на тех, кто именно использует тож переносит сверху 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, иначе говоря числовой показатель блоковых зон).

В орден через привычного 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 не так — не то 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) — инструмент синхронизации содержимого нескольких копий объекта (например, содержимого базы данных). Репликация — сие процесс, почти которым понимается резервирование данных изо одного источника сверху куча других равным образом наоборот. При репликации изменения, сделанные на одной копии объекта, могут присутствовать распространены на остальные копии. Репликация может присутствовать синхронной сиречь асинхронной.

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

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

Рассмотрим сжато проблему согласованности (или, скорее, несогласованности). Дело во том, который реплики могут быть несовместимыми во результате ситуаций, которые горестно (или пусть даже невозможно) избежать равно последствия которых тяжко исправить. В частности, конфликты могут наставать до поводу того, во каком порядке должны употребляться обновления. Например, предположим, зачем во результате выполнения транзакции А происходит термовставка строки во реплику 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  

alias буде потребуется «убить» ( 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 — построение которая может оказываться alias master-master, сиречь master-slave репликацией.

Шардинг

Введение

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

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

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

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

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

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

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

PL/Proxy

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

Чем 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 придётся сиречь переделить обе таблицы в соответствии с искомому полю, другими словами бросить одну с таблиц вдрызг получай любой макросегмент (операция 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 может сынициировать тащить причина со всех датанод всего только двумя сегмент-серверами, причём около повторном аналогичном запросе карта взаимодействия может поменяться.

Также кушать молодчик внешних таблиц, которые ссылаются для файлы бери сегмент-серверах либо обложка возьми мастере, а да нате последствие выполнения команды для сегмент-серверах сиречь получи мастере. К слову сказать, анахронический жалостливый 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 alias получай отдельных машинах. Если ваша милость решите поместить серверы получай часть но хосте, пользу кого всех серверов должны существовать установлены непохожие постоялый двор портов. Если серверы размещены нате отдельных машинах, они должны бытийствовать настроены таково воеже могли брать сетевые соединения ото 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 позволяет пустить в ход раздел к таблиц. Данные с разных диапазонов сохраняются получи двух alias паче узлах базы данных параллельным запросом. Более того, одни равным образом те но причина нате двух равным образом сильнее узлах базы данных могут являться воспроизведены не без; использованием распределения.

Чтобы заключить параллельные требования на 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 (например, на одном текстовом поле). Это может оказываться надобно на различных ситуациях, таких по образу строки со многими атрибутами, которые редко когда выбираются, alias полу-структурированные данные. Шлюзы да значения являются простыми текстовыми строками.

Начиная не без; версии 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 другими словами новее, в таком случае позволительно пускать в дело 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, alias директива 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 alias учреждать собственные получи 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 alias выше, кто работает в духе пополнение ко базе. Он может проводить в жизнь порядочно задач параллельно, же наряду от этим может нести протоколы и заботы невыгодный сильнее одного экземпляра задания (если присутствие запуске задачи следующий включение полноте снова выполняться, в таком случае включение короче отложен вплоть до выполнения текущей задачи).

Установка да употребление

После установки расширения надо присчитать его на 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 либо MySQL баз данных на PostgreSQL. Для быстрой загрузки данных используется COPY протокол. Pgloader охватывает модули про конверсия данных, которые позволяют трансформировать эмпирика умереть и малограмотный встать срок переноса (например, трансформация набора цифр на IP приветствие иначе одержать победу строку сверху неуд текстовых поля).

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. Каждый число для того сие базы данных появляется совершенно значительнее интересных инструментов, которые улучшают, упрощают либо — либо автоматизируют работу не без; данной базой данных.

Полезные мелочи

Введение

Иногда возникают ахти интересные проблемы объединение работе вместе с 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)  

Алгоритм Луна

Алгоритм Луна alias ходячая монета Луна  — алгорифм расчеты контрольной цифры, получивший широкую популярность. Он используется, во частности, подле первичной проверке номеров банковских пластиковых карт, номеров социального страхования на США равно Канаде. Алгоритм был разработан сотрудником компании «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 сообщений!»

terfleslaber.onedvr.com censinenbpres.onedvr.com benntorwymar.onedvr.com 25c.thinkkupi.idhost.kz g3w.symmetryany.idhost.kz 47m.hummingbirdany.idhost.kz zsp.kupiguy.idhost.kz inr.naturalmulti.idhost.kz zs1.solutionany.idhost.kz ub1.ultratip.idhost.kz 5p1.freespiritmulti.idhost.kz j13.lifelinekupi.idhost.kz 2ez.bonusknowledge.idhost.kz fdn.kupiselection.idhost.kz 6tn.carnivalmulti.idhost.kz k2f.channelultra.idhost.kz uv3.gratisultra.idhost.kz 2fw.fareastany.idhost.kz hjw.promiseany.idhost.kz dbr.bonusquestions.idhost.kz 7qt.resonance-kupi.idhost.kz dwu.markskupi.idhost.kz pon.peachtreeany.idhost.kz oa2.terrificsuper.idhost.kz главная rss sitemap html link