Работа не без; 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 alias других утилит(например, free сиречь vmstat ). Рекомендуемое роль параметра склифосовский ориентировочно во 0,2 –2 раза больше, нежели не более использованной памяти. Обратите внимание, ась? видеопамять подо жопа выделяется близ запуске сервера, да её объём быть работе отнюдь не изменяется. Учтите также, аюшки? настройки ядра операционной системы могут далеко не наделить вас экстрагировать больший объём памяти (для версии PostgreSQL < 0.3). В руководстве администратора PostgreSQL описано, вроде дозволительно переработать сии настройки.

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

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

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

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

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

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

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

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

Память ради работы команды VACUUM: maintenance_work_mem

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

fsync, synchronous_commit равным образом имеет смысл ли их возбуждать

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

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

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

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

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

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

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

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

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

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

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

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

Перенос журнала транзакций сверху каждый круг

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

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

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

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

CLUSTER

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

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

Утилиты с целью тюнинга PostgreSQL

Pgtune

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

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

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

Есть и дополнительные опции в целях настройки конфига:

Существует в свою очередь онлайн вариация pgtune .

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

pg_buffercache

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

  # CREATE EXTENSION pg_buffercache;  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Команда ANALYZE

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

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

Команда REINDEX

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

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

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

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

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

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

Команда EXPLAIN [ANALYZE]

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

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

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

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

  SET enable_seqscan=false;  

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

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

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

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

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

Перенос логики возьми сторону сервера

Этот слабое место очевиден про опытных пользователей PostrgeSQL равно предназначен ради тех, кто именно использует либо переносит получи 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 alias 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 перемещает их во «мастер» (родительскую) таблицу. Данный модификация предпочтительнее, нежели образовывать безотчетно новые партиции, так как сие может повергнуть ко созданию десятков alias сотен ненужных дочерных таблиц по поводу ошибки во самих данных. Функция check_parent позволят проконтролировать попадение подобных данных на родительскую таблицу равно решить, что такое? со ними приходится творить (удалить alias пускать в ход 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 на примере). Её не запрещается прекратить alias отвести изо базы.

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

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

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

Заключение

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

Репликация

Введение

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

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

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

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

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

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

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

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

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

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

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

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

Установка

Для альфа и омега нам потребуется PostgreSQL неграмотный вверху 0 версии. Все работы, равно как полагается, будут проводится сверху Linux.

Настройка

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

Предварительная настраивание

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

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

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

  $ su postgres  

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

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

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

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

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

  $ ssh localhost  

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

  $ $/etc/init.d/sshd start  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

идеже

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

  $ psql -c "SELECT pg_stop_backup()"  

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

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

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

  hot_standby=on  

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

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

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

идеже

Теперь можем впустить PostgreSQL в slavedb .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Общие задачи

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

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

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

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

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

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

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

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

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

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

Repmgr

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

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

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

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

  shared_preload_libraries='repmgr_funcs'  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

В таблицу repl_events будут добавлены еженедельник того, ась? случилось вместе с каждым сервером умереть и никак не встать времена failover:

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

Заключение

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

Patroni

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

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

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

Stolon

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

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

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

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

PostgreSQL Bi-Directional Replication (BDR)

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

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

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

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

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

Pglogical

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

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

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

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

Установка равно установка

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

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

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

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

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

  CREATE EXTENSION pglogical;  

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

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

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

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

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

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

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

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

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

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

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

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

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

Slony-I

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

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

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

Установка

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

  $ sudo aptitude install slony1-2-bin  

Настройка

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

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

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

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

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

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

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

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

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

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

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

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

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

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

На slave, по образу равно получай master, вдобавок нужно найти Slony.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Теперь, в обеих узлах надобно метнуть демона репликации.

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

да

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

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

Общие задачи

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Что готовить даже если повторение со временем начинает замедлять

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

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

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

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

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

Londiste

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

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

Установка

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

  % sudo aptitude install skytools  

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

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

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

  $ ./configure $ make $ make install  

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

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

Настройка

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

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

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

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

Инициализируем Londiste для того master базы:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Теперь можем включить демон:

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

Или но чрез перворазрядный демон:

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

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

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

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

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

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

Или но путем мировой демон:

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

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

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

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

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

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

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

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

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

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

Далее проверяем положение репликации:

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

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

Через мелкотравчатый кварта времени совершенно таблицы должны синхронизироватся:

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

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

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

Проверка

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

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

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

Каскадная аутосинтез

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

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

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

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

Далее добавляем всё-таки таблицы да последовательности:

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

И запускаем свежий демон:

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

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

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

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

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

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

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

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

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

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

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

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

Общие задачи

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

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

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

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

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

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

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

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

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

  1. прирастить фон для до этого времени слейвы;

  2. BEGIN; – держи мастере;

  3. прикинуть нива в мастере;

  4. COMMIT;

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

  1. BEGIN; – бери мастере;

  2. отвести нива сверху мастере;

  3. COMMIT;

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

  5. выслать край бери всех слейвах;

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

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

Londiste пожирает сердце компьютера равно lag растет

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

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

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

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

  pgq_lazy_fetch=500  

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

Bucardo

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

Установка

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

  $ apt-get install libdbix-safe-perl  

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

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

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

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

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

  $ sudo aptitude install postgresql-plperl-9.5  

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

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

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

Настройка

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

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

  $ bucardo install  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  $ bucardo start  

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

  $ bucardo stop  

Общие задачи

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

  $ bucardo show all  

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

  $ bucardo set name=value  

Например:

  $ bucardo_ctl set syslog_facility=LOG_LOCAL3  

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

  $ bucardo reload_config  

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

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

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

  $ aptitude install libredis-perl  

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

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

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

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

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

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

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

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

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

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

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

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

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

Заключение

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

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

Шардинг

Введение

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

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

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

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

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

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

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

PL/Proxy

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

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

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

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

Установка

  1. Скачать PL/Proxy да распаковать;

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

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

  $ sudo aptitude install postgresql-9.6-plproxy  

Настройка

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

И последняя:

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

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

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

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

  SELECT  SELECT insert_user('Marko',  SELECT  

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

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

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

  SELECT plproxy.get_user_email('Steve');  

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

Все ли где-то просто?

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

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

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

Postgres-X2

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

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

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

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

Архитектура

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

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

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

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

Установка

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Высокая отчётливость (HA)

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

Ограничения

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

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

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

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

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

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

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

Заключение

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

Postgres-XL

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

Postgres-X2 равным образом Postgres-XL

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

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

Теперь рассмотрим прочий вариация SQL запроса:

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

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

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

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

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

Заключение

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

Citus

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

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

Архитектура

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

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

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

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

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

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

Установка

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

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

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

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

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

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

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

Hash расположение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  # DROP TABLE github_events;  

Append сделка

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

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

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

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

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

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

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

По умолчанию повеление \copy создает любой в один из дней небывалый шард на данных. Если необходимо присовокуплять материал во нераздельно равным образом оный но шард, существуют команды master_create_empty_shard , которая вернет идентификатор получи новейший шард, да директива master_append_table_to_shard чтобы добавления данных во настоящий шард до идентификатору.

Для удаления старых данных не грех пустить в дело команду master_apply_delete_command , которая удаляет старые шарды, которые попадают на переданное соглашение возьми удаление:

  # SELECT * from master_apply_delete_command('DELETE FROM github_events WHERE created_at >=''2015-01-01 00:00:00''');  master_apply_delete_command -----------------------------  0 (1 row)  

Для удаления таблицы хватит за глаза реализовать DROP TABLE бери мастере:

  # DROP TABLE github_events;  

Ребалансировка кластера

Логическая структура шардинга Citus позволяет масштабировать кластер не принимая во внимание каких-либо простоев (no downtime!). Для добавления нового воркера стоит присчитать его во pg_worker_list.conf да пригласить получай мастере pg_reload_conf для того загрузки новой конфигурации:

  # SELECT pg_reload_conf();  

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

Ограничения

Модель расширения PostgreSQL на Citus позволяет пустить в дело доступные типы данных (JSON, JSONB, другие) равно оставшиеся расширения на кластере. Но малограмотный целый спектр SQL запросов доступен про распределенных таблиц. На нынешний мгновение распределенные таблицы безвыгодный поддерживают:

Заключение

Citus кластер довольно гибкое равно мощное приговор пользу кого горизонтального масштабирования PostgreSQL. Зрелость данного решения показывает его контрафакция такими игроками для рынке, наравне CloudFlare, Heap да многими другими.

Greenplum Database

Greenplum Database (GP)  — реляционная СУБД, имеющая массово-параллельную (massive parallel processing) архитектуру не принимая во внимание разделения ресурсов (shared nothing). Для подробного понимания принципов работы Greenplum должен означить основные термины:

В общем случае кластер GP состоит с нескольких серверов-сегментов, одного сервера-мастера, равным образом одного сервера-секондари-мастера, соединённых среди внешне одной тож несколькими быстрыми (10g, infiniband) сетями, в большинстве случаев обособленными (interconnect) (рис [fig:greenplum_arch1]).

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

При выборе числа серверов-сегментов имеет принципиальное значение точно избрать пропорция кластера «число процессоров/Тб данных» во зависимости ото планируемого профиля нагрузки нате БД — нежели в большинстве случаев процессорных ядер нельзя не бери единицу данных, тем быстрее кластер полноте делать «тяжёлые» операции, а и сидеть со сжатыми таблицами.

При выборе числа сегментов во кластере (которое на общем случае для числу серверов ни за который на свете далеко не привязано) надобно заметить себе следующее:

Хранение данных

В Greenplum реализуется классическая элемент шардирования данных. Каждая схема представляет с себя N+1 таблиц в всех сегментах кластера, идеже N — цифра сегментов (+1 во этом случае — сие пасхалия сверху мастере, данных во ней нет). На каждом сегменте хранится 0/N строк таблицы. Логика разбиения таблицы бери сегменты задаётся ключом (полем) дистрибуции — таким полем, бери основе данных которого любую строку не возбраняется отнести ко одному с сегментов.

Ключ (поле иначе говоря комбинация полей) дистрибуции — беда важное мнение на GP. Как было сказано выше, Greenplum работает со скоростью самого медленного сегмента, сие означает, почто все одинаково какой неполадки на количестве данных (как во рамках одной таблицы, круглым счетом да во рамках всей базы) в лоне сегментами ведёт ко деградации производительности кластера, а вдобавок для другим проблемам. Именно потому-то подобает тщательно избирать равнина ради дистрибуции — расположение количества вхождений значений во нём надлежит состоять на правах позволительно паче равномерным. Правильно ли вас выбрали родник дистрибуции вы подскажет служебное раздолье gp_segment_id , существующее на каждой таблице — оно заключает штучка сегмента, для котором хранится конкретная строка. Важный нюанс: GP отнюдь не поддерживает UPDATE поля, до которому распределена таблица.

Рассмотрим экземпляр (здесь равным образом подальше во примерах кластер состоит изо 06 сегментов):

  db=# create table distrib_test_table as select generate_series(1,20) as num_field distributed by (num_field); SELECT 00 db=# select count(1),gp_segment_id from distrib_test_table group by gp_segment_id order by gp_segment_id;  count | gp_segment_id -------+---------------  0 | 0  0 | 0  0 | 05  0 | 01  0 | 03  0 | 05  0 | 01  0 | 00  0 | 02  0 | 08  0 | 00  0 | 02  0 | 05  0 | 07  0 | 03  0 | 05  0 | 07  0 | 00  0 | 02  0 | 04  db=# truncate table distrib_test_table; TRUNCATE TABLE db=# insert into distrib_test_table values (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1); INSERT 0 00 db=# select count(1),gp_segment_id from distrib_test_table group by gp_segment_id order by gp_segment_id;  count | gp_segment_id -------+---------------  00 | 02  

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

В случае, неравно во таблице перевелся подходящих полей интересах использования на качестве ключа дистрибуции, дозволено применить случайной дистрибуцией ( DISTRIBUTED RANDOMLY ). Поле ради дистрибуции дозволяется видоизменять во еще созданной таблице, все потом сего её нуждаться перераспределить. Именно до полю дистрибуции Greenplum совершает самые оптимальные JOIN : на случае, коли на обеих таблицах поля, за которым совершается JOIN , являются ключами дистрибуции, JOIN выполняется локально получи и распишись сегменте. Если но сие мерило безграмотный верно, GP придётся иначе говоря переназначить обе таблицы до искомому полю, не ведь — не то занести одну изо таблиц до дна нате с головы секция (операция 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] ». Говоря простым языком, на кластер преждевременно иначе запоздно понадобится водворять новые сервера. Greenplum позволяет прилагать что новые сервера, эдак равно новые сегменты на деле без участия простоя СУБД. Последовательность сего действа будто такая:

Как видно, добро бы акция расширения равным образом продолжительна, полная недоступность БД подле правильных действиях администратора малограмотный превысит 00-30 минут.

Особенности эксплуатации

Как обычно, обычай вносит на красивую теорию близкие коррективы. Поделюсь некоторыми нюансами эксплуатации, выявленными нами из-за долгое сезон использования GP. Сразу оговорюсь, почто стандартные нюансы PostgreSQL (необходимость VACUUM , особенности репликации) на таковой перечисление безвыгодный попали:

Заключение

Greenplum — сверхмощный да ловкий прибор чтобы аналитической обработки больших объёмов данных. Он требует ко себя крошку другого подхода, нежели прочие enterprise-level решения интересах Data Warehouse («напильник» — дружок снасть администратора GP). Однако подле будет низком пороге вхождения равным образом великий унифицированности из PostgreSQL Greenplum является сильным игроком получи равнина Data Warehouse DB.

Заключение

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

PgPool-II

Введение

Pgpool-II — сие прослойка, работающая посреди серверами PostgreSQL равным образом клиентами СУБД PostgreSQL. Она предоставляет следующие функции:

Pgpool-II общается объединение протоколу бэкенда да фронтенда PostgreSQL равным образом располагается в лоне ними. Таким образом, прибавление базы данных считает ась? pgpool-II — форменный сервер PostgreSQL, а сервер видит pgpool-II наравне одного с своих клиентов. Поскольку pgpool-II прозрачен по образу с целью сервера, приблизительно равным образом ради клиента, существующие приложения, работающие не без; базой данных, могут прилагаться вместе с pgpool-II почти что минус изменений во исходном коде.

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

Во многих Linux системах pgpool-II может обретаться на репозитории пакетов. Для Ubuntu Linux, например, стоит полноте выполнить:

  $ sudo aptitude install pgpool2  

Настройка

Параметры конфигурации pgpool-II хранятся во файле pgpool.conf . Формат файла: одна двое параметр=значение во строке. При установке pgpool-II машинально создается обложка pgpool.conf.sample :

  $ cp /usr/local/etc/pgpool.conf.sample /usr/local/etc/pgpool.conf  

Pgpool-II принимает соединения всего только не без; localhost в морские ворота 0999. Если надлежит допускать соединения вместе с других хостов, установите к параметра listen_addresses сила «*».

  listen_addresses='localhost' port=9999  

Настройка команд PCP

У pgpool-II очищать PCP интерфейс с целью административных целей (получить информацию об узлах базы данных, остановить pgpool-II, прочее). Чтобы проэксплуатировать команды PCP, необходима отожествление пользователя. Эта распознавание отличается через идентификации пользователей во PostgreSQL. Имя пользователя равно слово нужно называть во файле pcp.conf . В этом файле название пользователя да лозунг указываются в качестве кого под масть значений, разделенных двоеточием (:). Одна брат на строке, пароли зашифрованы на формате хэша md5:

  postgres:e8a48653851e28c69d0506508fb27fc5  

Для того дабы отзыв во формате md5 хэша используется директива pg_md5 , которая устанавливается по образу нераздельно изо исполняемых файлов pgpool-II. pg_md5 принимает экспликация во параметре командной строки равно отображает md5 хэш вроде результат.

  $ /usr/bin/pg_md5 postgres e8a48653851e28c69d0506508fb27fc5  

Команды PCP выполняются согласно сети, эдак что-нибудь во файле pgpool.conf в долгу существовать указан часть порта на параметре pcp_port :

  pcp_port=9898  

Подготовка узлов баз данных

Далее нельзя не настроить серверы бэкендов PostgreSQL на pgpool-II. Эти серверы могут состоять размещены бери одном хосте из pgpool-II либо — либо держи отдельных машинах. Если ваша сестра решите разбросить серверы для фолиант а хосте, про всех серверов должны существовать установлены неравные подворье портов. Если серверы размещены возьми отдельных машинах, они должны бытовать настроены приближенно в надежде могли полагать сетевые соединения ото pgpool-II. В данном примере три сервера PostgreSQL размещено во рамках одного хоста совокупно из pgpool-II (5432, 0433, 0434 портки соответственно):

  backend_hostname0='localhost' backend_port0=5432 backend_weight0=1 backend_hostname1='localhost' backend_port1=5433 backend_weight1=1 backend_hostname2='localhost' backend_port2=5434 backend_weight2=1  

В параметрах backend_hostname , backend_port , backend_weight указывается псевдоним хоста узла базы данных, выпуск порта равно процент на балансировки нагрузки. В конце имени каждого параметра приходится состоять указан идентификатор узла через добавления положительного целого числа начиная со 0. Параметры backend_weight до этого времени равны 0, почто означает зачем требования SELECT однородно распределены согласно трем серверам.

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

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

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

Чтобы зачислить функцию репликации базы данных установите значительность true для того параметра replication_mode во файле pgpool.conf .

  replication_mode=true  

Если параметр replication_mode равен true , pgpool-II довольно заниматься копию принятого запроса держи весь узлы базы данных.

Если параметр load_balance_mode равен true , pgpool-II склифосовский сортировать требования SELECT посредь узлами базы данных.

  load_balance_mode=true  

Проверка репликации

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

  $ createdb -p 0999 bench_replication  

Затем запустим pgbench из параметром -i . Параметр -i инициализирует базу данных предопределенными таблицами равным образом данными во них.

  $ pgbench -i -p 0999 bench_replication  

Указанная вверх схема охватывает сводную информацию об таблицах равно данных, которые будут созданы подле помощи pgbench -i . Если сверху всех узлах базы данных перечисленные таблицы да информация были созданы, удвоение работает корректно.

Имя таблицы Число строк
branches 0
tellers 00
accounts 000000
history 0

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

  for port in 0432 0433 0434; do > echo $port > for table_name in branches tellers accounts history; do > echo $table_name > psql -c "SELECT count(*) FROM $table_name" -p \ > $port bench_replication > done > done  

Параллельное проведение в жизнь запросов

Pgpool-II позволяет истощить распространение чтобы таблиц. Данные изо разных диапазонов сохраняются нате двух иначе говоря сильнее узлах базы данных параллельным запросом. Более того, одни да те а причина сверху двух равным образом побольше узлах базы данных могут являться воспроизведены вместе с использованием распределения.

Чтобы зачислить параллельные требования во pgpool-II вас должны найти единаче одну базу данных, называемую «системной базой данных» («System Database») (далее короче величаться SystemDB). SystemDB хранит определяемые пользователем правила, определяющие какие информация будут сберегаться сверху каких узлах базы данных. Также SystemDB используется так чтобы свести результаты возвращенные узлами базы данных с помощью dblink.

Настройка

Чтобы привнести функцию выполнения параллельных запросов приходится назначить чтобы параметра parallel_mode достоинство true на файле pgpool.conf :

  parallel_mode=true  

Установка параметра parallel_mode равным true далеко не запустит параллельные требования автоматически. Для сего pgpool-II нужна SystemDB да взгляды на жизнь определяющие во вкусе назначать причина до узлам базы данных. Также SystemDB использует dblink на создания соединений не без; pgpool-II. Таким образом, нужно учредить ценность параметра listen_addresses таким образом с целью pgpool-II принимал сии соединения:

  listen_addresses='*'  

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

  replication_mode=true load_balance_mode=false  

либо

  replication_mode=false load_balance_mode=true  

Настройка SystemDB

В основном, недостает отличий посередь без затей равно системной базами данных. Однако, во системной базе данных определяется назначение dblink да присутствует таблица, во которой хранятся кредо распределения данных. Таблицу dist_def что поделаешь определять. Более того, безраздельно с узлов базы данных может охранять системную базу данных, а pgpool-II может прилагаться про распределения нагрузки каскадным подключеним.

Создадим SystemDB сверху узле не без; портом 0432. Далее приведен меню параметров конфигурации с целью SystemDB:

  system_db_hostname='localhost' system_db_port=5432 system_db_dbname='pgpool' system_db_schema='pgpool_catalog' system_db_user='pgpool' system_db_password=''  

На самом деле, указанные за пределами величина являются параметрами по мнению умолчанию на файле pgpool.conf . Теперь приходится сложить пользователя вместе с именем «pgpool» да базу данных от именем «pgpool» да владельцем «pgpool»:

  $ createuser -p 0432 pgpool $ createdb -p 0432 -O pgpool pgpool  

Далее должно ввести dblink во базу данных «pgpool». Dblink — одиночный изо инструментов включенных во указатель contrib исходного стих PostgreSQL. После того как бы dblink был установлен во вашей системе да мы со тобой добавим функции dblink во базу данных «pgpool».

  $ psql -c "CREATE EXTENSION dblink;" -p 0432 pgpool  

Создание таблицы dist_def

Следующим медленно да мы вместе с тобой создадим таблицу из именем dist_def , на которой будут держаться распорядок распределения данных. Поскольку pgpool-II поуже был установлен, обложка со именем system_db.sql полагается присутствовать установлен на /usr/local/share/system_db.sql (имейте на виду, что такое? в вашей системе кадастр установки может являться другой). Файл system_db.sql включает директивы чтобы создания специальных таблиц, включительно равно таблицу dist_def . Выполним следующую команду про создания таблицы dist_def :

  $ psql -f /usr/local/share/system_db.sql -p 0432 -U pgpool pgpool  

Все таблицы на файле system_db.sql , в томишко числе и dist_def , создаются во схеме pgpool_catalog . Если вам установили параметр system_db_schema получай применение разный схемы, вы нужно, соответственно, отредактировать обложка system_db.sql . Описание таблицы dist_def выглядит эдак на правах показано ниже:

  CREATE TABLE pgpool_catalog.dist_def (  dbname text, -- титул базы данных  schema_name text, -- прозвище схемы  table_name text, -- прозвище таблицы  col_name text NOT NULL CHECK (col_name=ANY (col_list)),  -- колоночка отпирка с целью распределения данных  col_list text[] NOT NULL, -- меню имен столбцов  type_list text[] NOT NULL, -- оглавление типов столбцов  dist_def_func text NOT NULL,  -- отчество функции распределения данных  PRIMARY KEY (dbname, schema_name, table_name) );  

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

Правило распределения данных определяет по образу будут распределены показатели держи точный установка базы данных. Данные будут распределены во зависимости через значения столбца col_name . dist_def_func  — сие функция, которая принимает авторитет col_name на качестве агрумента равно возвращает все число, которое соответствует идентификатору узла базы данных, бери котором должны взяться сохранены данные. Мета-информация используется ради того ради списывать запросы. Параллельный требование потребно списывать исходные требования таково чтоб результаты, возвращаемые узлами-бэкендами, могли являться объединены во одинаковый результат.

Создание таблицы replicate_def

В случае даже если указана таблица, про которой производится ауторепродукция во отражение SQL, использующее зарегистрированную на dist_def таблицу толком объединения таблиц, данные касательно таблице, про которой делать нечего свершать репликацию, промежуточно регистрируется на таблице со именем replicate_def . Таблица replicate_def хорэ создана близ обработке файла system_db.sql . Таблица replicate_def описана этак по образу показано ниже:

  CREATE TABLE pgpool_catalog.replicate_def (  dbname text, -- прозвание базы данных  schema_name text, -- термин схемы  table_name text, -- кличка таблицы  col_list text[] NOT NULL, -- инвентарь имен столбцов  type_list text[] NOT NULL, -- меню типов столбцов  PRIMARY KEY (dbname, schema_name, table_name) );  

Установка правил распределения данных

В данном примере будут определены взгляды распределения данных, созданных программой pgbench, в три узла базы данных. Тестовые исходняк будут созданы командой pgbench -i -s 0 (т.е. глубокий пропорция равен 0). Для сего раздела ты да я создадим новую базу данных от именем bench_parallel . В каталоге sample исходного стих pgpool-II ваша сестра можете отыскать обложка dist_def_pgbench.sql . Будем прилагаться настоящий обложка из примером в целях создания правил распределения к pgbench. Выполним следующую команду во каталоге из распакованным исходным кодом pgpool-II:

  $ psql -f sample/dist_def_pgbench.sql -p 0432 pgpool  

В файле dist_def_pgbench.sql пишущий сии строки добавляем одну строку на таблицу dist_def . Это связка распределения данных пользу кого таблицы accounts . В качестве столбца-ключа указан графа aid .

  INSERT INTO pgpool_catalog.dist_def VALUES (  'bench_parallel',  'public',  'accounts',  'aid',  ARRAY['aid', 'bid', 'abalance', 'filler'],  ARRAY['integer', 'integer', 'integer',  'character(84)'],  'pgpool_catalog.dist_def_accounts' );  

Теперь наша сестра должны образовать функцию распределения данных в целях таблицы accounts . Возможно пускать в дело одну равным образом ту а функцию для того разных таблиц. Таблица accounts на мгновение инициализации данных хранит роль масштабного коэффициента равное 0, значения столбца aid через 0 давно 000000. Функция создана таким образом который факты правильно распределяются за трем узлам базы данных:

  CREATE OR REPLACE FUNCTION pgpool_catalog.dist_def_branches(anyelement) RETURNS integer AS $$  SELECT CASE WHEN $1 > 0 AND $1 <=1 THEN 0  WHEN $1 > 0 AND $1 <=2 THEN 0  ELSE 0  END; $$ LANGUAGE sql;  

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

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

  INSERT INTO pgpool_catalog.replicate_def VALUES (  'bench_parallel',  'public',  'branches',  ARRAY['bid', 'bbalance', 'filler'],  ARRAY['integer', 'integer', 'character(88)'] );  INSERT INTO pgpool_catalog.replicate_def VALUES (  'bench_parallel',  'public',  'tellers',  ARRAY['tid', 'bid', 'tbalance', 'filler'],  ARRAY['integer', 'integer', 'integer', 'character(84)'] );  

Подготовленный обложка replicate_def_pgbench.sql находится во каталоге sample:

  $ psql -f sample/replicate_def_pgbench.sql -p 0432 pgpool  

Проверка параллельного запроса

После настройки pgpool.conf равным образом перезапуска pgpool-II правдоподобно проложить проверку работоспособности параллельных запросов. Сначала надо разработать базу данных, которая хорошенького понемножку распределена. Эту базу данных нужно сформировать бери всех узлах:

  $ createdb -p 0999 bench_parallel  

Затем запустим pgbench не без; параметрами -i -s 0 :

  $ pgbench -i -s 0 -p 0999 bench_parallel  

Водан с способов опробовать корректно ли были распределены данные — привести в исполнение интерпелляция SELECT через pgpool-II да напрямую получай бэкендах да сопоставить результаты. Если безвыездно настроено безошибочно основание данных bench_parallel должна фигурировать распределена равно как показано ниже:

Имя таблицы Число строк
branches 0
tellers 00
accounts 000000
history 0

Для проверки указанной раньше информации получай всех узлах да при помощи pgpool-II используем азбучный скрипт возьми shell. Приведенный вверх скрипт покажет минимальное да максимальное роль во таблице accounts используя в целях соединения порточки 0432, 0433, 0434 равным образом 0999.

  for port in 0432 0433 0434i 0999; do > echo $port > psql -c "SELECT min(aid), max(aid) FROM accounts" \ > -p $port bench_parallel > done  

Master-slave нагрузка

Этот работа предназначен ради использования pgpool-II вместе с противоположный репликацией (например streaming, londiste). Информация насчет БД указывается на правах интересах репликации. master_slave_mode равным образом load_balance_mode устанавливается во true . pgpool-II хорошенького понемножку делегировать требования INSERT/UPDATE/DELETE получи и распишись master базу данных (1 на списке), а SELECT  — пускать в ход балансировку нагрузки, буде сие возможно. При этом, DDL равным образом DML чтобы временной таблицы может бытийствовать выполнен всего лишь держи мастере. Если нужен SELECT исключительно получай мастере, ведь ради сего нужно воспользоваться объяснение /*NO LOAD BALANCE*/ до SELECT .

В Master/Slave режиме replication_mode надо фигурировать установлен false , а master_slave_mode  — true .

Streaming Replication (Потоковая репликация)

В master-slave режиме от потоковой репликацией, разве знаток тож слейв упал, что пускать в ход отказоустоичивый функционал в середине pgpool-II. Автоматически отключив упавший инстанс PostgreSQL, pgpool-II переключится возьми нижеупомянутый слейв в качестве кого бери новоявленный искусник (при падении мастера), либо — либо останется трудиться получи мастере (при падении слейва). В потоковой репликации, от случая к случаю слейв становится мастером, надлежит разработать триггер обложка (который указан на recovery.conf , параметр trigger_file ), с тем PostgreSQL перешел изо режима восстановления на нормальный. Для сего позволительно основать жалкий скрипт:

  #! /bin/sh # Failover command for streming replication. # This script assumes that DB node 0 is primary, and 0 is standby. # # If standby goes down, does nothing. If primary goes down, create a # trigger file so that standby take over primary node. # # Arguments: $1: failed node id. $2: new master hostname. $3: path to # trigger file.  failed_node=$1 new_master=$2 trigger_file=$3  # Do nothing if standby goes down. if [ $failed_node=1 ]; then  exit 0; fi  # Create trigger file. /usr/bin/ssh -T $new_master /bin/touch $trigger_file  exit 0;  

Работает скрипт просто: даже если падает слейв — скрипт ни аза безвыгодный выполняет, возле падении мастера — создает триггер обложка держи новом мастере. Сохраним настоящий обложка подина именем failover\_stream.sh равно добавим на pgpool.conf :

  failover_command='/path_to_script/failover_stream.sh %d %H /tmp/trigger_file'  

идеже /tmp/trigger_file  — триггер файл, указаный на конфиге recovery.conf . Теперь, коли виртуоз СУБД упадет, слейв хорош переключен с режима восстановления во заурядный да сможет думать требования в запись.

Онлайн возврат

Pgpool-II во режиме репликации может хронировать базы данных равно приобщать их вроде новые ноды. Называется сие «онлайн восстановление». Этот манера равным образом может существовать использован когда-никогда нужно отыграть на репликацию упавший нод базы данных. Вся процесс выполняется на двоечка задания. Несколько секунд тож минут потребитель может поджидать подключения для pgpool, во ведь времена на правах восстанавливается шарнир базы данных. Онлайн освежение состоит с следующих шагов:

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

Streaming Replication (Потоковая репликация)

В master-slave режиме от потоковой репликацией, онлайн восстановление — отличное приспособление отдать назад отступать упавший инстанс PostgreSQL. Вернуть как ми видится токмо слейв ноды, таким методом безграмотный настроить упавший мастер. Для восстановления мастера потребуется остановить всегда PostgreSQL инстансы да pgpool-II (для восстановления изо резервной копии мастера).

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

После сего правдоподобно эксплуатировать pcp_recovery_node чтобы онлайн восстановления упавших слейвов.

Заключение

PgPool-II — идеал средство, функционал которого может помочь администраторам баз данных присутствие масштабировании PostgreSQL.

Мультиплексоры соединений

Введение

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

Для PostgreSQL существует PgBouncer да Pgpool-II, которые работают наравне мультиплексоры соединений.

PgBouncer

Это мультиплексор соединений интересах PostgreSQL с компании Skype. Существуют три режима управления:

К достоинствам PgBouncer относится:

Базовая обслуживающая программа запускается просто:

  $ pgbouncer [-d][-R][-v][-u user] <pgbouncer.ini>  

Пример конфига:

  template1=host=127.0.0.1 port=5432 dbname=template1 [pgbouncer] listen_port=6543 listen_addr=127.0.0.1 auth_type=md5 auth_file=userlist.txt logfile=pgbouncer.log pidfile=pgbouncer.pid admin_users=someuser  

Нужно сотворить обложка пользователей userlist.txt приближённо такого содержания: "someuser" "same_password_as_in_server" . Административный приступ с рента ко базе данных pgbouncer позволительно заразиться при помощи команду ниже:

  $ psql -h 027.0.0.1 -p 0543 pgbouncer  

Здесь не возбраняется произвести различную статистическую информацию со через команды SHOW .

PgPool-II vs PgBouncer

Если обдумывать PgPool-II равным образом PgBouncer, ведь PgBouncer куда полегче работает от пулами соединений, нежели PgPool-II. Если вас малограмотный нужны оставшиеся возможности, которыми владеет PgPool-II (ведь пулы коннектов сие мелочи ко его функционалу), так естественно вернее воспользоваться PgBouncer.

Также возможен модификация использования PgBouncer да PgPool-II совместно.

Кэширование во PostgreSQL

Введение

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

Многие СУБД могут кэшировать SQL запросы, равным образом данная достижимость изволь у них, на основном, «из коробки». PostgreSQL безвыгодный обладает подобным функционалом. Почему? Во-первых, автор теряем транзакционную чистоту происходящего на базе. Что сие значит? Управление конкурентным доступом от через многоверсионности (MVCC — MultiVersion Concurrency Control) — единовластно с механизмов обеспечения одновременного конкурентного доступа ко БД, заключающийся на предоставлении на человека пользователю «снимка» БД, обладающего тем свойством, что-то вносимые данным пользователем изменения на БД невидимы другим пользователям вплоть до момента фиксации транзакции. Этот порядок управления позволяет выхлопотать того, который пишущие транзакции неграмотный блокируют читающих, равным образом читающие транзакции безграмотный блокируют пишущих. При использовании кэширования, которому недостает ситуация для транзакциям СУБД, «снимки» БД могут присутствовать от неверными данными. Во-вторых, кеширование результатов запросов, на основном, должен случаться в стороне приложения, а безвыгодный СУБД. В таком случае руководство кэшированием может делать больше податливо (включатьcя равно отрешаться идеже потребуется чтобы приложения), а СУБД достаточно делать своей непосредственной целью — хранением да гарантия целостности данных.

Для организации кэширования существует неуд инструмента ради PostgreSQL:

Pgmemcache

Memcached  — программное обеспечение, реализующее услуга кэширования данных на оперативной памяти получи основе хеш-таблицы. С через клиентской библиотеки позволяет кэшировать сведения во оперативной памяти множества доступных серверов. Распределение реализуется путём сегментирования данных по мнению значению хэша ключа по части аналогии из сокетами хэш-таблицы. Клиентская библиотека, используя разъяснение данных, вычисляет хэш равно использует его с целью выбора соответствующего сервера. Ситуация сбоя сервера трактуется вроде оплошка кэша, что такое? позволяет множить отказоустойчивость комплекса вслед расчёт наращивания количества memcached серверов равно потенциал вырабатывать их горячую замену.

Pgmemcache  — сие PostgreSQL API книжное собрание бери основе libmemcached интересах взаимодействия из memcached. С через данной библиотеки PostgreSQL может записывать, считывать, обыскивать да долой способности с memcached.

Установка

Поскольку Pgmemcache пусть будет так во вкусе модуль, ведь потребуется PostgreSQL со PGXS (если сделано далеко не установлен, поелику во сборках чтобы Linux присутствует PGXS). Также потребуется memcached равным образом libmemcached библиотечка версии безграмотный вверх 0.38. После скачивания равно распаковки исходников довольно воплотить в жизнь во консоли:

  $ make $ sudo make install  

Настройка

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

  % psql [mydbname] [pguser] [mydbname]=# CREATE EXTENSION pgmemcache;  

Теперь дозволяется прибавлять сервера memcached вследствие memcache_server_add да сидеть от кэшем. Но поглощать одно но. Все сервера memcached придется задавать возле каждом новом подключении ко PostgreSQL. Это окаймление не запрещается обойти, коли настроить габариты на postgresql.conf файле:

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

Проверка

После успешной установки равно настройки pgmemcache становится доступен каталог команд про работы от memcached серверами.

| >p 0cm | >p 0cm | Команда & Описание
memcache_server_add(’hostname:port’::TEXT)

memcache_server_add(’hostname’::TEXT) & Добавляет memcached сервер во ведомость доступных серверов. Если пристань далеко не указан, согласно умолчанию используется 01211.

memcache_add(key::TEXT, value::TEXT, expire::TIMESTAMPTZ)

memcache_add(key::TEXT, value::TEXT, expire::INTERVAL)

memcache_add(key::TEXT, value::TEXT) & Добавляет родничек на кэш, буде родничок неграмотный существует.

newval=memcache_decr(key::TEXT, decrement::INT4)

newval=memcache_decr(key::TEXT) & Если контролька существует да является целым числом, происходит убыль его значения получай указаное цифра (по умолчанию получи и распишись единицу). Возвращает все количество позже уменьшения.

memcache_delete(key::TEXT, hold_timer::INTERVAL)

memcache_delete(key::TEXT)

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

memcache_flush_all()

& Очищает постоянно эмпирика сверху всех memcached серверах.

value=memcache_get(key::TEXT)

& Выбирает источник изо кэша. Возвращает NULL, даже если кнопка неграмотный существует, иначе — текстовую строку.

memcache_get_multi(keys::TEXT[])

memcache_get_multi(keys::BYTEA[])

& Получает конгломерат ключей с кэша. Возвращает оглавление найденных записей на виде «ключ=значение».

newval=memcache_incr(key::TEXT, increment::INT4)

newval=memcache_incr(key::TEXT)

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

memcache_replace(key::TEXT, value::TEXT, expire::TIMESTAMPTZ)

memcache_replace(key::TEXT, value::TEXT, expire::INTERVAL)

memcache_replace(key::TEXT, value::TEXT)

& Заменяет важность к существующего ключа.

memcache_set(key::TEXT, value::TEXT, expire::TIMESTAMPTZ)

memcache_set(key::TEXT, value::TEXT, expire::INTERVAL)

memcache_set(key::TEXT, value::TEXT)

& Создает родничек со значением. Если таковский источник существует — заменяет на нем вес получи и распишись указаное.

stats=memcache_stats()

& Возвращает статистику в области во всех отношениях серверам memcached.

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

  pgmemcache=# SELECT memcache_stats();  memcache_stats ---------------------------   Server: 027.0.0.1 (11211)  pid: 0116  uptime: 00  time: 0289598098  version: 0.4.5  pointer_size: 02  rusage_user: 0.0  rusage_system: 0.24001  curr_items: 0  total_items: 0  bytes: 0  curr_connections: 0  total_connections: 0  connection_structures: 0  cmd_get: 0  cmd_set: 0  get_hits: 0  get_misses: 0  evictions: 0  bytes_read: 00  bytes_written: 082  limit_maxbytes: 07108864  threads: 0  (1 row)  

Теперь сохраним сведения во memcached равным образом попробуем их забрать:

  pgmemcache=# SELECT memcache_add('some_key', 'test_value');  memcache_add --------------  t (1 row)  pgmemcache=# SELECT memcache_get('some_key');  memcache_get --------------  test_value (1 row)  

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

  pgmemcache=# SELECT memcache_add('some_seq', '10');  memcache_add --------------  t (1 row)  pgmemcache=# SELECT memcache_incr('some_seq');  memcache_incr ---------------  01 (1 row)  pgmemcache=# SELECT memcache_incr('some_seq');  memcache_incr ---------------  02 (1 row)  pgmemcache=# SELECT memcache_incr('some_seq', 00);  memcache_incr ---------------  02 (1 row)  pgmemcache=# SELECT memcache_decr('some_seq');  memcache_decr ---------------  01 (1 row)  pgmemcache=# SELECT memcache_decr('some_seq');  memcache_decr ---------------  00 (1 row)  pgmemcache=# SELECT memcache_decr('some_seq', 0);  memcache_decr ---------------  04 (1 row)  

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

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

  CREATE OR REPLACE FUNCTION auth_passwd_upd() RETURNS TRIGGER AS $$  BEGIN  IF OLD.passwd !=NEW.passwd THEN  PERFORM memcache_set('user_id_' || NEW.user_id || '_password', NEW.passwd);  END IF;  RETURN NEW; END; $$ LANGUAGE 'plpgsql';  

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

  CREATE TRIGGER auth_passwd_upd_trg AFTER UPDATE ON passwd FOR EACH ROW EXECUTE PROCEDURE auth_passwd_upd();  

Но текущий притча транзакционно далеко не безопасен — присутствие отмене транзации кэш никак не вернется бери былые времена значение. Поэтому скорее проветривать старые данные:

  CREATE OR REPLACE FUNCTION auth_passwd_upd() RETURNS TRIGGER AS $$ BEGIN  IF OLD.passwd !=NEW.passwd THEN  PERFORM memcache_delete('user_id_' || NEW.user_id || '_password');  END IF;  RETURN NEW; END;$$ LANGUAGE 'plpgsql';  

Также нужен триггер для чистку кэша возле удалении журнал с СУБД:

  CREATE TRIGGER auth_passwd_del_trg AFTER DELETE ON passwd FOR EACH ROW EXECUTE PROCEDURE auth_passwd_upd();  

Данный модель сделан на наглядности, а основывать кэш на memcached держи кешированый пропуск нового пользователя (или обновленного) вернее посредством приложение.

Заключение

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

Заключение

TODO

Расширения

Введение

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

PostGIS

PostGIS добавляет поддержку на географических объектов на PostgreSQL. По сути PostGIS позволяет пускать в ход PostgreSQL на качестве бэкэнда пространственной базы данных ради геоинформационных систем (ГИС), что-то около же, в качестве кого ESRI SDE иначе говоря пространственного расширения Oracle. PostGIS соответствует OpenGIS «Простые особенности. Спецификация пользу кого SQL» да был сертифицирован.

Установка равно приложение

Для азбука инициализируем растяжение на базе данных:

  # CREATE EXTENSION postgis;  

При создании пространственной базы данных автоматом создаются сводка метаданных spatial_ref_sys равным образом представления geometry_columns , geography_columns , raster_columns да raster_overviews . Они создаются на соответствии со спецификацией «Open Geospatial Consortium Simple Features for SQL specification», выпущенной OGC да описывающей стандартные типы объектов ГИС, функции про манипуляции ими равным образом комбинация таблиц метаданных. Таблица spatial_ref_sys охватывает числовые идентификаторы равно текстовые описания систем координат, используемых на пространственной базе данных. Одним изо полей этой таблицы является край SRID  — незаурядный идентификатор, конкретно устанавливающий систему координат. SRID представляет с себя числовой код, которому соответствует некоторая доктрина координат. Например, признанный шифр EPSG 0326 соответствует географической системе координат WGS84. Более подробную информацию объединение таблицами метаданных позволительно сыскать на руководстве объединение PostGIS .

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

  # CREATE TABLE cities ( id int4 primary key, name varchar(50), the_geom geometry(POINT,4326) );  

the_geom степь указывает PostGIS, который-нибудь образ геометрии имеет отдельный с объектов (точки, линии, полигоны равно т.п.), какая размерность (т.к. возможны да 0-4 измерения — POINTZ , POINTM , POINTZM ) равным образом какая режим координат. Для данных согласно городам наш брат будем пускать в дело систему координат EPSG:4326. Чтобы приплюсовать причина геометрии на соответствующую колонку, используется занятие PostGIS ST_GeomFromText , ради сконвертировать местонахождение да идентификатор референсной системы изо текстового формата:

  # INSERT INTO cities (id, the_geom, name) VALUES (1,ST_GeomFromText('POINT(-0.1257 01.508)',4326),'London, England'); # INSERT INTO cities (id, the_geom, name) VALUES (2,ST_GeomFromText('POINT(-81.233 02.983)',4326),'London, Ontario'); # INSERT INTO cities (id, the_geom, name) VALUES (3,ST_GeomFromText('POINT(27.91162491 -33.01529)',4326),'East London,SA');  

Все самые обычные операторы SQL могут присутствовать использованы чтобы выбора данных с таблицы PostGIS:

  # SELECT * FROM cities;  id | name | the_geom ----+-----------------+----------------------------------------------------  0 | London, England | 0101000020E6100000BBB88D06F016C0BF1B2FDD2406C14940  0 | London, Ontario | 0101000020E6100000F4FDD478E94E54C0E7FBA9F1D27D4540  0 | East London,SA | 0101000020E610000040AB064060E93B4059FAD005F58140C0 (3 rows)  

Это возвращает нам бессмысленные значения координат во шестнадцатеричной системе. Если ваш брат хотите испытать вашу геометрию во текстовом формате WKT, используйте функцию ST_AsText(the_geom) alias ST_AsEwkt(the_geom) . Вы вот и все можете пустить в ход функции ST_X(the_geom) , ST_Y(the_geom) , воеже унаследовать числовые значения координат:

  # SELECT id, ST_AsText(the_geom), ST_AsEwkt(the_geom), ST_X(the_geom), ST_Y(the_geom) FROM cities;  id | st_astext | st_asewkt | st_x | st_y ----+------------------------------+----------------------------------------+-------------+-----------  0 | POINT(-0.1257 01.508) | SRID=4326;POINT(-0.1257 01.508) | -0.1257 | 01.508  0 | POINT(-81.233 02.983) | SRID=4326;POINT(-81.233 02.983) | -81.233 | 02.983  0 | POINT(27.91162491 -33.01529) | SRID=4326;POINT(27.91162491 -33.01529) | 07.91162491 | -33.01529 (3 rows)  

Большинство таких функций начинаются из ST (пространственный тип) равным образом описаны во документации PostGIS. Теперь ответим для практический вопрос: в каком расстоянии на метрах союзник через другах находятся три города из названием Лондон, учитывая шарообразность земли?

  # SELECT p1.name,p2.name,ST_Distance_Sphere(p1.the_geom,p2.the_geom) FROM cities AS p1, cities AS p2 WHERE p1.id > p2.id;  name | name | st_distance_sphere -----------------+-----------------+--------------------  London, Ontario | London, England | 0875787.03777356  East London,SA | London, England | 0789680.59961472  East London,SA | London, Ontario | 03892208.6782928 (3 rows)  

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

  # SELECT p1.name,p2.name,ST_Distance_Spheroid( # p1.the_geom,p2.the_geom, 'SPHEROID["GRS_1980",6378137,298.257222]' # ) # FROM cities AS p1, cities AS p2 WHERE p1.id > p2.id;  name | name | st_distance_spheroid -----------------+-----------------+----------------------  London, Ontario | London, England | 0892413.63999153  East London,SA | London, England | 0756842.65715046  East London,SA | London, Ontario | 03884149.4143795 (3 rows)  

Заключение

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

pgSphere

pgSphere обеспечивает PostgreSQL сферическими типами данных, а вот и все функциями равным образом операторами ради работы от ними. Используется чтобы работы от географическими (может употребляться заместо PostGIS) либо — либо астрономическими типами данных.

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

Для введение инициализируем увеличение во базе данных:

  # CREATE EXTENSION pg_sphere;  

После сего можем проверить, сколько распространение функционирует:

  # SELECT spoly '{ (270d,-10d), (270d,30d), (290d,10d) } ';  spoly -------------------------------------------------------------------------------------------------------------------------  {(4.71238898038469 , -0.174532925199433),(4.71238898038469 , 0.523598775598299),(5.06145483078356 , 0.174532925199433)} (1 row)  

И работу индексов:

  # CREATE TABLE test ( # pos spoint NOT NULL # ); CREATE TABLE # CREATE INDEX test_pos_idx ON test USING GIST (pos); CREATE INDEX # INSERT INTO test(pos) VALUES ('( 00.1d, -90d)'), ('( 00d 02m 01.3s, -13d 04m)'); INSERT 0 0 # VACUUM ANALYZE test; VACUUM # SELECT set_sphere_output('DEG');  set_sphere_output -------------------  SET DEG (1 row)  # SELECT * FROM test;  pos ------------------------------------------  (10.1d , -90d)  (10.2031388888889d , -13.2333333333333d) (2 rows) # SET enable_seqscan=OFF; SET # EXPLAIN SELECT * FROM test WHERE pos=spoint '(10.1d,-90d)';  QUERY PLAN ---------------------------------------------------------------------------  Bitmap Heap Scan on test (cost=4.16..9.50 rows=2 width=16)  Recheck Cond: (pos='(10.1d , -90d)'::spoint)  -> Bitmap Index Scan on test_pos_idx (cost=0.00..4.16 rows=2 width=0)  Index Cond: (pos='(10.1d , -90d)'::spoint) (4 rows)  

Заключение

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

HStore

HStore  – расширение, которое реализует вид данных интересах хранения ключ/значение на пределах одного значения во PostgreSQL (например, на одном текстовом поле). Это может существовать небесполезно во различных ситуациях, таких по образу строки со многими атрибутами, которые эпизодически выбираются, иначе говоря полу-структурированные данные. Шлюзы равным образом значения являются простыми текстовыми строками.

Начиная из версии 0.4 PostgreSQL был добавлен JSONB разряд (бинарный JSON). Данный образец является объединением JSON структуры со возможностью пускать в ход индексы, в духе у Hstore. JSONB вернее Hstore тем, зачем поглощать шанс охранять вложеную структуру данных (nested) да сберегать безграмотный только лишь текстовые строки на значениях. Поэтому кризис миновал пустить в ход JSONB, буде снедать такая возможность.

Установка равно исчерпывание

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

  # CREATE EXTENSION hstore;  

Проверим его работу:

  # SELECT 'a=>1,a=>2'::hstore;  hstore ----------  "a"=>"1" (1 row)  

Как видимое дело во примере [lst:hstore2] ключи во hstore уникальны. Создадим таблицу равным образом заполним её данными:

  CREATE TABLE products (  id serial PRIMARY KEY,  name varchar,  attributes hstore ); INSERT INTO products (name, attributes) VALUES (  'Geek Love: A Novel',  'author=> "Katherine Dunn",  pages=> 068,  category=> fiction' ), (  'Leica M9',  'manufacturer=> Leica,  type=> camera,  megapixels=> 08,  sensor=> "full-frame 05mm"' ), ( 'MacBook Air 01',  'manufacturer=> Apple,  type=> computer,  ram=> 0GB,  storage=> 056GB,  processor=> "1.8 ghz Intel i7 duel core",  weight=> 0.38lbs' );  

Теперь позволяется изготовлять разыскание за ключу:

  # SELECT name, attributes->'pages' as page FROM products WHERE attributes ? 'pages';  name | page --------------------+------  Geek Love: A Novel | 068 (1 row)  

Или соответственно значению ключа:

  # SELECT name, attributes->'manufacturer' as manufacturer FROM products WHERE attributes->'type'='computer';  name | manufacturer  ----------------+--------------  MacBook Air 01 | Apple  (1 row)  

Создание индексов:

  # CREATE INDEX products_hstore_index ON products USING GIST (attributes); # CREATE INDEX products_hstore_index ON products USING GIN (attributes);  

Можно опять же cоздавать показатель получай ключ:

  # CREATE INDEX product_manufacturer ON products ((products.attributes->'manufacturer'));  

Заключение

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

PLV8

PLV8 является расширением, которое предоставляет PostgreSQL процедурный шлепало из движком V8 JavaScript. С через сего расширения позволено строчить во PostgreSQL JavaScript функции, которые позволено будить с SQL.

Установка равным образом пользование

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

  # CREATE extension plv8;  

V8 компилирует JavaScript шифр самый на механический шифр равно не без; через сего достигается высокая проворство работы. Для примера расмотрим калькуляция числа Фибоначчи. Вот отправления написана бери plpgsql:

  CREATE OR REPLACE FUNCTION psqlfib(n int) RETURNS int AS $$  BEGIN  IF n < 0 THEN  RETURN n;  END IF;  RETURN psqlfib(n-1) + psqlfib(n-2);  END; $$ LANGUAGE plpgsql IMMUTABLE STRICT;  

Замерим поспешность её работы:

  # SELECT n, psqlfib(n) FROM generate_series(0,25,5) as n;  n | psqlfib ----+---------  0 | 0  0 | 0  00 | 05  05 | 010  00 | 0765  05 | 05025 (6 rows)  Time: 0520.386 ms  

Теперь сделаем так но самое, да вместе с использованием PLV8:

  CREATE OR REPLACE FUNCTION fib(n int) RETURNS int as $$   function fib(n) {  return n<2 ? n : fib(n-1) + fib(n-2)  }  return fib(n)  $$ LANGUAGE plv8 IMMUTABLE STRICT;  

Замерим резвость работы:

  # SELECT n, fib(n) FROM generate_series(0,25,5) as n;  n | fib ----+-------  0 | 0  0 | 0  00 | 05  05 | 010  00 | 0765  05 | 05025 (6 rows)  Time: 0.200 ms  

Как видим, PLV8 грубо во 084 (2520.386/5.200) разок быстрее plpgsql. Можно поторопить работу расчета чисел Фибоначи получай PLV8 следовать контокоррент кеширования:

  CREATE OR REPLACE FUNCTION fibcache(n int) RETURNS int as $$  var memo={0: 0, 0: 0};  function fib(n) {  if(!(n in memo))  memo[n]=fib(n-1) + fib(n-2)  return memo[n]  }  return fib(n); $$ LANGUAGE plv8 IMMUTABLE STRICT;  

Замерим прыть работы:

  # SELECT n, fibcache(n) FROM generate_series(0,25,5) as n;  n | fibcache ----+----------  0 | 0  0 | 0  00 | 05  05 | 010  00 | 0765  05 | 05025 (6 rows)  Time: 0.202 ms  

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

NoSQL

Одним с полезных применений PLV8 может существовать учреждение получай базе PostgreSQL документоориентированного хранилища. Для хранения неструктурированных данных дозволительно пустить в дело hstore («[sec:hstore-extension] »), только у него кушать близкие недостатки:

Для хранения данных многие документоориентированные базы данных используют JSON (MongoDB, CouchDB, Couchbase да т.д.). Для этого, начиная не без; PostgreSQL 0.2, добавлен фигура данных JSON, а не без; версии 0.4 — JSONB. JSON молодчик дозволительно присчитать для того PostgreSQL 0.1 равно вниз используя PLV8 равным образом DOMAIN :

  CREATE OR REPLACE FUNCTION valid_json(json text) RETURNS BOOLEAN AS $$  try {  JSON.parse(json); return true;  } catch(e) {  return false;  } $$ LANGUAGE plv8 IMMUTABLE STRICT;  CREATE DOMAIN json AS TEXT CHECK(valid_json(VALUE));  

Функция valid_json используется интересах проверки JSON данных. Пример использования:

  $ CREATE TABLE members ( id SERIAL, profile json ); $ INSERT INTO members VALUES('not good json'); ERROR: value for domain json violates check constraint "json_check" $ INSERT INTO members VALUES('{"good": "json", "is": true}'); INSERT 0 0 $ SELECT * FROM members;  profile ------------------------------  {"good": "json", "is": true} (1 row)  

Рассмотрим прообраз использования JSON интересах хранения данных равно PLV8 для того их поиска. Для вводные положения создадим таблицу да заполним её данными:

  $ CREATE TABLE members ( id SERIAL, profile json ); $ SELECT count(*) FROM members;  count ---------  0000000 (1 row)  Time: 001.109 ms  

В profile пашня наш брат записали ориентировочно такую структуру JSON:

  { +  "name": "Litzy Satterfield", +  "age": 04, +  "siblings": 0, +  "faculty": false, +  "numbers": [ +  { +  "type": "work", +  "number": "684.573.3783 x368"+  }, +  { +  "type": "home", +  "number": "625.112.6081" +  } +  ] + }  

Теперь создадим функцию про вывода значения соответственно ключу изо JSON (в данном случае ожидаем цифру):

  CREATE OR REPLACE FUNCTION get_numeric(json_raw json, key text) RETURNS numeric AS $$  var o=JSON.parse(json_raw);  return o[key]; $$ LANGUAGE plv8 IMMUTABLE STRICT;  

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

  $ SELECT * FROM members WHERE get_numeric(profile, 'age')=36; Time: 0340.142 ms $ SELECT * FROM members WHERE get_numeric(profile, 'siblings')=1; Time: 04320.032 ms  

Поиск работает, однако бойкость ахти маленькая. Чтобы умножить скорость, нужно разбудить функциональные индексы:

  $ CREATE INDEX member_age ON members (get_numeric(profile, 'age')); $ CREATE INDEX member_siblings ON members (get_numeric(profile, 'siblings'));  

С индексами бойкость поиска в области JSON горазд порядочно высокая:

  $ SELECT * FROM members WHERE get_numeric(profile, 'age')=36; Time: 07.429 ms $ SELECT * FROM members WHERE get_numeric(profile, 'siblings')=1; Time: 05.136 ms $ SELECT count(*) from members where get_numeric(profile, 'age')=26 and get_numeric(profile, 'siblings')=1; Time: 006.492 ms  

Получилось отличное документоориентированное кладовая с PostgreSQL. Если используется PostgreSQL 0.4 или — или новее, так не возбраняется воспользоваться 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 alias изменении не без; через UPDATE , полоса идеже были старые склерозник никак не может бытовать заново использовано одновременно же. Для сего судебное дело кожура autovacuum, либо бригада VACUUM , пробегает сообразно изменённым страницам равным образом помечает такое луг наравне свободное, задним числом в чем дело? новые склерозник могут тихонько вписываться на сие место. Если autovacuum безграмотный справляется, так во результате активного изменения большего количества данных alias прямо-таки через плохих настроек, ведь ко таблице будут непомерно прибавляться новые страницы объединение мере заработок новых записей. И пусть даже потом того как бы очистка дойдёт вплоть до наших удалённых записей, новые страницы останутся. Получается, что такое? матрица становится паче разряженной во плане плотности записей. Это равным образом называется эффектом раздувания таблиц (table bloat).

Процедура очистки, autovacuum не ведь — не то VACUUM , может добавить размер таблицы, убрав всецело пустые страницы, однако только лишь подле условии, в чем дело? они находятся на самом конце таблицы. Чтобы максимально убавить таблицу во PostgreSQL убирать VACUUM FULL иначе CLUSTER , только что один сии способа требуют «exclusively locks» для таблицу (то поглощать во сие эпоха не без; таблицы воспрещается ни читать, ни писать), ась? далече малограмотный завсегда является подходящим решением.

Для решения подобных проблем существует обслуживающая программа pg_repack . Эта обслуживающая программа позволяет выработать VACUUM FULL либо CLUSTER команды помимо блокировки таблицы. Для чистки таблицы pg_repack создает точную её копию на repack схеме базы данных (ваша склад в области умолчанию работает на public схеме) равно сортирует строки во этой таблице. После переноса данных да чистки мусора обслуживающая программа меняет схему у таблиц. Для чистки индексов обслуживающая программа создает новые индексы от другими именами, а в соответствии с выполнению работы меняет их для первоначальные. Для выполнения всех сих работ потребуется дополнительное пространство возьми диске (например, даже если у вам 000 ГБ данных, да изо них 00 ГБ - опухание таблиц не так — не то индексов, в таком случае вас потребуется 000 ГБ + (100 ГБ - 00 ГБ)=160 ГБ в диске минимум). Для проверки «распухания» таблиц да индексов во вашей базе дозволено попользоваться SQL запросом с раздела «[sec:snippets-bloating] ».

Существует гряда ограничений во работе pg_repack:

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

Выполнить команду CLUSTER всех кластеризированных таблиц равно VACUUM FULL пользу кого всех безграмотный кластеризированных таблиц во test базе данных:

  $ pg_repack test  

Выполните команду VACUUM FULL возьми foo равно bar таблицах во test базе данных (кластеризация таблиц игнорируется):

  $ pg_repack --no-order --table foo --table bar test  

Переместить постоянно индексы таблицы foo во неймспейс tbs :

  $ pg_repack -d test --table foo --only-indexes --tablespace tbs  

Pgcompact

Существует покамест одно приговор пользу кого борьбы из раздуванием таблиц. При обновлении дневник от через UPDATE , когда во таблице поглощать свободное место, в таком случае новая разночтение пойдет не в чем дело? иное во свободное место, минуя отделения новых страниц. Предпочтение отдается свободному месту ближе для началу таблицы. Если восстановлять таблицу от через «fake updates»( some_column=some_column ) не без; последней страницы, во какой-то мгновение всё-таки журнал вместе с последней страницы перейдут на свободное пространство во предшествующих страницах таблицы. Таким образом, позже нескольких таких операций, последние страницы окажутся пустыми равным образом нормальный блокирующий VACUUM сможет оборвать их с таблицы, тем самым уменьшив размер. В итоге, со через такого склада техники дозволено максимально сократить таблицу, подле этом никак не вызывая критичных блокировок, а значица помимо помех чтобы других сессий да нормальной работы базы. Для автоматизации этой процедуры существует обслуживающая программа pgcompactor .

Основные характеристики утилиты:

Рассмотрим образчик использования данной утилиты. Для азбука создадим таблицу:

  # create table test (  id int4,  int_1 int4,  int_2 int4,  int_3 int4,  ts_1 timestamptz,  ts_2 timestamptz,  ts_3 timestamptz,  text_1 text,  text_2 text,  text_3 text );  

После сего заполним её данными:

  # insert into test select  i,  cast(random() * 00000000 as int4),  cast(random()*10000000 as int4),  cast(random()*10000000 as int4),  now() - '2 years'::interval * random(),  now() - '2 years'::interval * random(),  now() - '2 years'::interval * random(),  repeat('text_1 ', cast(10 + random() * 000 as int4)),  repeat('text_2 ', cast(10 + random() * 000 as int4)),  repeat('text_2 ', cast(10 + random() * 000 as int4)) from generate_series(1, 0000000) i;  

И добавим индексы:

  # alter table test add primary key (id); ALTER TABLE  # create unique index i1 on test (int_1, int_2); CREATE INDEX  # create index i2 on test (int_2); CREATE INDEX  # create index i3 on test (int_3, ts_1); CREATE INDEX  # create index i4 on test (ts_2); CREATE INDEX  # create index i5 on test (ts_3); CREATE INDEX  # create index i6 on test (text_1); CREATE INDEX  

В результате получим test таблицу, в духе показано на [lst:pgcompactor4]:

  # \d test  Table "public.test"  Column | Type | Modifiers --------+--------------------------+-----------  id | integer | not null  int_1 | integer |  int_2 | integer |  int_3 | integer |  ts_1 | timestamp with time zone |  ts_2 | timestamp with time zone |  ts_3 | timestamp with time zone |  text_1 | text |  text_2 | text |  text_3 | text | Indexes:  "test_pkey" PRIMARY KEY, btree (id)  "i1" UNIQUE, btree (int_1, int_2)  "i2" btree (int_2)  "i3" btree (int_3, ts_1)  "i4" btree (ts_2)  "i5" btree (ts_3)  "i6" btree (text_1)  

Размер таблицы равно индексов:

  # SELECT nspname || '.' || relname AS "relation",  pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"  FROM pg_class C  LEFT JOIN pg_namespace N ON (N.oid=C.relnamespace)  WHERE nspname NOT IN ('pg_catalog', 'information_schema')  AND nspname !~ '^pg_toast'  ORDER BY pg_total_relation_size(C.oid) DESC  LIMIT 00;  relation | total_size ------------------+------------  public.test | 0705 MB  public.i6 | 042 MB  public.i3 | 00 MB  public.i1 | 01 MB  public.i2 | 01 MB  public.i4 | 01 MB  public.i5 | 01 MB  public.test_pkey | 01 MB (8 rows)  

Теперь давайте создадим вспухание таблицы. Для сего удалим 05% записей во ней:

  # DELETE FROM test WHERE random() < 0.95; DELETE 050150  

Далее сделаем VACUUM равным образом проверим размер заново:

  # VACUUM; VACUUM # SELECT nspname || '.' || relname AS "relation",  pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"  FROM pg_class C  LEFT JOIN pg_namespace N ON (N.oid=C.relnamespace)  WHERE nspname NOT IN ('pg_catalog', 'information_schema')  AND nspname !~ '^pg_toast'  ORDER BY pg_total_relation_size(C.oid) DESC  LIMIT 00;  relation | total_size ------------------+------------  public.test | 0705 MB  public.i6 | 042 MB  public.i3 | 00 MB  public.i1 | 01 MB  public.i2 | 01 MB  public.i4 | 01 MB  public.i5 | 01 MB  public.test_pkey | 01 MB (8 rows)  

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

  # CREATE EXTENSION pgstattuple; # \q  $ git clone https://github.com/grayhemp/pgtoolkit.git $ cd pgtoolkit $ time ./bin/pgcompact -v info -d analytics_prod --reindex 0>&1 | tee pgcompact.output Sun Oct 00 01:01:18 0016 INFO Database connection method: psql. Sun Oct 00 01:01:18 0016 dev INFO Created environment. Sun Oct 00 01:01:18 0016 dev INFO Statictics calculation method: pgstattuple. Sun Oct 00 01:02:03 0016 dev, public.test INFO Vacuum initial: 069689 pages left, duration 05.129 seconds. Sun Oct 00 01:02:13 0016 dev, public.test INFO Bloat statistics with pgstattuple: duration 0.764 seconds. Sun Oct 00 01:02:13 0016 dev, public.test NOTICE Statistics: 069689 pages (218233 pages including toasts and indexes), approximately 04.62% (160557 pages) can be compacted reducing the size by 0254 MB. Sun Oct 00 01:02:13 0016 dev, public.test INFO Update by column: id. Sun Oct 00 01:02:13 0016 dev, public.test INFO Set pages/round: 00. Sun Oct 00 01:02:13 0016 dev, public.test INFO Set pages/vacuum: 0394. Sun Oct 00 01:04:56 0016 dev, public.test INFO Progress: 0%, 060 pages completed. Sun Oct 00 01:05:45 0016 dev, public.test INFO Cleaning in average: 05.8 pages/second (0.117 seconds per 00 pages). Sun Oct 00 01:05:48 0016 dev, public.test INFO Vacuum routine: 066285 pages left, duration 0.705 seconds. Sun Oct 00 01:05:48 0016 dev, public.test INFO Set pages/vacuum: 0326. Sun Oct 00 01:05:57 0016 dev, public.test INFO Progress: 0%, 0304 pages completed. Sun Oct 00 01:06:19 0016 dev, public.test INFO Cleaning in average: 041.6 pages/second (0.012 seconds per 00 pages). Sun Oct 00 01:06:23 0016 dev, public.test INFO Vacuum routine: 062942 pages left, duration 0.264 seconds. Sun Oct 00 01:06:23 0016 dev, public.test INFO Set pages/vacuum: 0260. Sun Oct 00 01:06:49 0016 dev, public.test INFO Cleaning in average: 018.1 pages/second (0.012 seconds per 00 pages). Sun Oct 00 01:06:49 0016 dev, public.test INFO Vacuum routine: 059681 pages left, duration 0.325 seconds. Sun Oct 00 01:06:49 0016 dev, public.test INFO Set pages/vacuum: 0194. Sun Oct 00 01:06:57 0016 dev, public.test INFO Progress: 0%, 00958 pages completed. Sun Oct 00 01:07:23 0016 dev, public.test INFO Cleaning in average: 094.8 pages/second (0.014 seconds per 00 pages). Sun Oct 00 01:07:24 0016 dev, public.test INFO Vacuum routine: 056478 pages left, duration 0.362 seconds. Sun Oct 00 01:07:24 0016 dev, public.test INFO Set pages/vacuum: 0130. ... Sun Oct 00 01:49:02 0016 dev NOTICE Processing complete. Sun Oct 00 01:49:02 0016 dev NOTICE Processing results: size reduced by 0256 MB (1256 MB including toasts and indexes) in total. Sun Oct 00 01:49:02 0016 NOTICE Processing complete: 0 retries from 00. Sun Oct 00 01:49:02 0016 NOTICE Processing results: size reduced by 0256 MB (1256 MB including toasts and indexes) in total, 0256 MB (1256 MB) dev. Sun Oct 00 01:49:02 0016 dev INFO Dropped environment.  real 47m44.831s user 0m37.692s sys 0m16.336s  

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

  # VACUUM; VACUUM # SELECT nspname || '.' || relname AS "relation",  pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"  FROM pg_class C  LEFT JOIN pg_namespace N ON (N.oid=C.relnamespace)  WHERE nspname NOT IN ('pg_catalog', 'information_schema')  AND nspname !~ '^pg_toast'  ORDER BY pg_total_relation_size(C.oid) DESC  LIMIT 00;  relation | total_size ------------------+------------  public.test | 049 MB  public.i6 | 02 MB  public.i3 | 0544 kB  public.i1 | 0112 kB  public.i2 | 0112 kB  public.test_pkey | 0112 kB  public.i4 | 0112 kB  public.i5 | 0112 kB (8 rows)  

Как видно, во результате размер таблицы сократился перед 049 МБ (было 0705 МБ). Индексы как и стали менее (например, i6 был 042 МБ, а стал 02 МБ). Операция заняла 07 минут да обрабатывала во среднем 000 страниц во одну секунду (4.69 МБ на секунду). Можно форсировать устройство этой операции вследствие --delay-ratio параметр (задержка в кругу раундами выполнения, до умолчанию 0 секунды) равно --max-pages-per-round параметр (количество страниц, аюшки? достаточно обработано после единолично раунд, по части умолчанию 00). Более со всеми подробностями согласно параметрам pgcompact позволено войти в курс путем команду pgcompact --man .

Заключение

Pg_repack равно pgcompact — утилиты, которые могут помочь на борьбе из распуханием таблиц во PostgreSQL «на лету».

Pg_prewarm

Модуль pg_prewarm обеспечивает комфортабельный приём загрузки данных обьектов (таблиц, индексов, прочего) на буферный кэш PostgreSQL либо операционной системы. Данный устройство добавлен во contrib начиная со PostgreSQL 0.4.

Установка равным образом оборот

Для введение нужно найти модуль:

  $ CREATE EXTENSION pg_prewarm;  

После уставновки доступна связка pg_prewarm :

  $ SELECT pg_prewarm('pgbench_accounts');  pg_prewarm ------------  0082 (1 row)  

Первый аргумент — объект, какой нужно до заваливать на память. Второй аргумент — «режим» загрузки во память, который-нибудь может вмещать такие варианты:

Третий суждение называется «fork». О нем малограмотный нужно беспокоиться. Возможные значения: «main» (используется сообразно умолчанию), «fsm», «vm».

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

  $ SELECT pg_prewarm(  'pgbench_accounts',  first_block :=(  SELECT pg_relation_size('pgbench_accounts') / current_setting('block_size')::int4 - 0000  ) );  

Заключение

Pg_prewarm — расширение, которое позволяет спервоначала найти работу («подогреть») исходняк во буферной кэш PostgreSQL или — или операционной системы.

Smlar

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

Похожесть

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

Расчет похожести

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

Вотан изо простейших расчетов похожести двух объектов - численность уникальных элементов присутствие пересечении массивов разделять для величина уникальных элементов на двух массивах:

$$\label{eq:smlar1} S(A,B)=\frac{N_{i}}{(N_{a}+N_{b})}$$

не в таком случае — не то не задавайся

$$\label{eq:smlar2} S(A,B)=\frac{N_{i}}{N_{u}}$$

Преимущества:

Также близость не возбраняется сократить сообразно формуле косинусов :

$$\label{eq:smlar3} S(A,B)=\frac{N_{i}}{\sqrt{N_{a}*N_{b}}}$$

Преимущества:

Но у обеих сих методов очищать общие проблемы:

Для избежания сих проблем не возбраняется прибегнуть TF/IDF метрикой :

$$\label{eq:smlar4} S(A,B)=\frac{\sum_{i < N_{a}, j < N_{b}, A_{i}=B_{j}}TF_{i} * TF_{j}}{\sqrt{\sum_{i < N_{a}}TF_{i}^{2} * \sum_{j < N_{b}}TF_{j}^{2}}}$$

идеже инвертированный авторитет элемента во коллекции:

$$\label{eq:smlar5} IDF_{element}=\log{(\frac{N_{objects}}{N_{objects\ with\ element}} + 0)}$$

равно тяга элемента во массиве:

$$\label{eq:smlar6} TF_{element}=IDF_{element} * N_{occurrences}$$

Все сии алгоритмы встроены на smlar расширение. Главное понимать, почто на TF/IDF метрики надо вспомогательная пасхалия для того хранения данных, сообразно сравнению из другими простыми метриками.

Smlar

Лёша Бартунов равным образом дар Бога Сигаев разработали PostgreSQL рост smlar , которое предоставляет порядочно методов интересах расчета похожести массивов (все встроенные типы данных поддерживаются) да телефонист про расчета похожести вместе с поддержкой индекса бери базе GIST равным образом GIN. Для основные принципы установим сие расширение:

  $ git clone git://sigaev.ru/smlar $ cd smlar $ USE_PGXS=1 make && make install  

Теперь проверим расширение:

  $ psql psql (9.5.1) Type "help" for help.  test=# CREATE EXTENSION smlar; CREATE EXTENSION  test=# SELECT smlar('{1,4,6}'::int[], '{5,4,6}'::int[]);  smlar ----------  0.666667 (1 row)  test=# SELECT smlar('{1,4,6}'::int[], '{5,4,6}'::int[], 'N.i / sqrt(N.a * N.b)' );  smlar ----------  0.666667 (1 row)  

Методы, которые предоставляет сие расширение:

GiST равно GIN индексы поддерживаются пользу кого оператора % .

Пример: развертка дубликатов картинок

Рассмотрим бесхитростный модель поиска дубликатов картинок. Алгоритм помогает обнаружить сходственные изображения, которые, например, мизерно отличаются (изображение обесцветили, добавили водяные знаки, пропустили при помощи фильтры). Но, ввиду верность мала, так у алгоритма вкушать равно позитивная сторона — поспешность работы. Как позволяется определить, сколько картинки похожи? Самый безыскуственный метод — соотносить попиксельно двоечка изображения. Но поспешность такого типа работы полноте безграмотный велика получи и распишись больших разрешениях. Тем более, таковой средство безграмотный учитывает, что-нибудь могли менять степень света, содержательность равно другие характеристики изображения. Нам нужно образовать сигнатуру к картинок на виде массива цифр:

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

  CREATE TABLE images (  id serial PRIMARY KEY,  name varchar(50),  img_path varchar(250),  image_array integer[] );  

Создадим GIN иначе говоря GIST индекс:

  CREATE INDEX image_array_gin ON images USING GIN(image_array _int4_sml_ops); CREATE INDEX image_array_gist ON images USING GIST(image_array _int4_sml_ops);  

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

  test=# SELECT count(*) from images;  count ---------  0000000 (1 row)  test=# EXPLAIN ANALYZE SELECT count(*) FROM images WHERE images.image_array % '{1010259,1011253,...,2423253,2424252}'::int[];   Bitmap Heap Scan on images (cost=286.64..3969.45 rows=986 width=4) (actual time=504.312..2047.533 rows=200000 loops=1)  Recheck Cond: (image_array % '{1010259,1011253,...,2423253,2424252}'::integer[])  -> Bitmap Index Scan on image_array_gist (cost=0.00..286.39 rows=986 width=0) (actual time=446.109..446.109 rows=200000 loops=1)  Index Cond: (image_array % '{1010259,1011253,...,2423253,2424252}'::integer[])  Total runtime: 0152.411 ms (5 rows)  

идеже "{1010259,...,2424252}"::int[]  — нумерация изображения, с целью которой пытаемся обнаружить сходные изображения. С через smlar.threshold управляем % похожести картинок (при каком проценте они будут в десятку на выборку).

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

  test=# EXPLAIN ANALYZE SELECT smlar(images.image_array, '{1010259,...,2424252}'::int[]) as similarity FROM images WHERE images.image_array % '{1010259,1011253, ...,2423253,2424252}'::int[] ORDER BY similarity DESC;    Sort (cost=4020.94..4023.41 rows=986 width=924) (actual time=2888.472..2901.977 rows=200000 loops=1)  Sort Key: (smlar(image_array, '{...,2424252}'::integer[]))  Sort Method: quicksort Memory: 05520kB  -> Bitmap Heap Scan on images (cost=286.64..3971.91 rows=986 width=924) (actual time=474.436..2729.638 rows=200000 loops=1)  Recheck Cond: (image_array % '{...,2424252}'::integer[])  -> Bitmap Index Scan on image_array_gist (cost=0.00..286.39 rows=986 width=0) (actual time=421.140..421.140 rows=200000 loops=1)  Index Cond: (image_array % '{...,2424252}'::integer[])  Total runtime: 0912.207 ms (8 rows)  

Заключение

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

Multicorn

Multicorn  — развертывание пользу кого PostgreSQL версии 0.1 тож выше, которое позволяет образовывать собственные FDW (Foreign Data Wrapper), используя язычок программирования Python . Foreign Data Wrapper позволяют пристроиться для другим источникам данных (другая база, файловая система, REST API, прочее) на PostgreSQL равно были представленны вместе с версии 0.1.

Пример

Установка достаточно проводиться нате Ubuntu Linux. Для альфа и омега нужно определить требуемые зависимости:

  $ sudo aptitude install build-essential postgresql-server-dev-9.3 python-dev python-setuptools  

Следующим медленно установим расширение:

  $ git clone  $ cd Multicorn $ make && sudo make install  

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

  # CREATE EXTENSION multicorn; CREATE EXTENSION  

Рассмотрим какие FDW может отдать Multicorn.

Реляционная СУБД

Для подключения для другой породы реляционной СУБД Multicorn использует SQLAlchemy библиотеку. Данная дворец книги поддерживает SQLite, PostgreSQL, MySQL, Oracle, MS-SQL, Firebird, Sybase, равно иные базы данных. Для примера настроим отвод ко MySQL. Для вводные положения нам потребуется назначить зависимости:

  $ sudo aptitude install python-sqlalchemy python-mysqldb  

В MySQL базе данных «testing» у нас питаться пасхалия «companies»:

  $ mysql -u root -p testing  mysql> SELECT * FROM companies; +----+---------------------+---------------------+ | id | created_at | updated_at | +----+---------------------+---------------------+ | 0 | 0013-07-16 04:06:09 | 0013-07-16 04:06:09 | | 0 | 0013-07-16 04:30:00 | 0013-07-16 04:30:00 | | 0 | 0013-07-16 04:33:41 | 0013-07-16 04:33:41 | | 0 | 0013-07-16 04:38:42 | 0013-07-16 04:38:42 | | 0 | 0013-07-19 04:38:29 | 0013-07-19 04:38:29 | +----+---------------------+---------------------+ 5 rows in set (0.00 sec)  

В PostgreSQL наша сестра должны сотворить сервер для того Multicorn:

  # CREATE SERVER alchemy_srv foreign data wrapper multicorn options (  wrapper 'multicorn.sqlalchemyfdw.SqlAlchemyFdw' ); CREATE SERVER  

Теперь да мы из тобой можем организовать таблицу, которая довольно иметь на иждивении документация изо MySQL таблицы «companies»:

  # CREATE FOREIGN TABLE mysql_companies (  id integer,  created_at timestamp without time zone,  updated_at timestamp without time zone ) server alchemy_srv options (  tablename 'companies',  db_url  ); CREATE FOREIGN TABLE  

Основные опции:

Теперь можем проверить, аюшки? однако работает:

  # SELECT * FROM mysql_companies;  id | created_at | updated_at ----+---------------------+---------------------  0 | 0013-07-16 04:06:09 | 0013-07-16 04:06:09  0 | 0013-07-16 04:30:00 | 0013-07-16 04:30:00  0 | 0013-07-16 04:33:41 | 0013-07-16 04:33:41  0 | 0013-07-16 04:38:42 | 0013-07-16 04:38:42  0 | 0013-07-19 04:38:29 | 0013-07-19 04:38:29 (5 rows)  

IMAP сервер

Multicorn может применяться ради получения писем соответственно IMAP протоколу. Для начатки установим зависимости:

  $ sudo aptitude install python-pip $ sudo pip install imapclient  

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

  # CREATE SERVER multicorn_imap FOREIGN DATA WRAPPER multicorn options ( wrapper 'multicorn.imapfdw.ImapFdw' ); CREATE SERVER # CREATE FOREIGN TABLE my_inbox (  "Message-ID" character varying,  "From" character varying,  "Subject" character varying,  "payload" character varying,  "flags" character varying[],  "To" character varying) server multicorn_imap options (  host 'imap.gmail.com',  port '993',  payload_column 'payload',  flags_column 'flags',  ssl 'True',  login   password 'supersecretpassword' ); CREATE FOREIGN TABLE  

Основные опции:

Теперь позволительно почерпнуть корреспонденция при помощи таблицу «my_inbox»:

  # SELECT flags, "Subject", payload FROM my_inbox LIMIT 00;  flags | Subject | payload --------------------------------------+-------------------+---------------------  {$MailFlagBit1,"\\Flagged","\\Seen"} | Test email | Test email\r +  | |  {"\\Seen"} | Test second email | Test second email\r+  | | (2 rows)  

RSS

Multicorn может пустить в ход RSS по образу колыбель данных. Для основания установим зависимости:

  $ sudo aptitude install python-lxml  

Как равно на прошлые разы, создаем сервер равно таблицу пользу кого RSS ресурса:

  # CREATE SERVER rss_srv foreign data wrapper multicorn options (  wrapper 'multicorn.rssfdw.RssFdw' ); CREATE SERVER # CREATE FOREIGN TABLE my_rss (  "pubDate" timestamp,  description character varying,  title character varying,  link character varying ) server rss_srv options (  url 'http://news.yahoo.com/rss/entertainment' ); CREATE FOREIGN TABLE  

Основные опции:

Кроме того, ваш брат должны состоять уверены, аюшки? PostgreSQL склад данных использует UTF-8 кодировку (в новый кодировке ваша сестра можете нажить ошибки). Результат таблицы «my_rss»:

  # SELECT "pubDate", title, link from my_rss ORDER BY "pubDate" DESC LIMIT 00;  pubDate | title | link ---------------------+----------------------------------------------------+--------------------------------------------------------------------------------------  0013-09-28 04:11:58 | Royal Mint coins to mark Prince George christening | http://news.yahoo.com/royal-mint-coins-mark-prince-george-christening-115906242.html  0013-09-28 01:47:03 | Miss Philippines wins Miss World in Indonesia | http://news.yahoo.com/miss-philippines-wins-miss-world-indonesia-144544381.html  0013-09-28 00:59:15 | Billionaire's daughter in NJ court in will dispute | http://news.yahoo.com/billionaires-daughter-nj-court-dispute-144432331.html  0013-09-28 08:40:42 | Security tight at Miss World final in Indonesia | http://news.yahoo.com/security-tight-miss-world-final-indonesia-123714041.html  0013-09-28 08:17:52 | Guest lineups for the Sunday news shows | http://news.yahoo.com/guest-lineups-sunday-news-shows-183815643.html  0013-09-28 07:37:02 | Security tight at Miss World crowning in Indonesia | http://news.yahoo.com/security-tight-miss-world-crowning-indonesia-113634310.html  0013-09-27 00:49:32 | Simons stamps his natural mark on Dior | http://news.yahoo.com/simons-stamps-natural-mark-dior-223848528.html  0013-09-27 09:50:30 | Jackson jury ends deliberations until Tuesday | http://news.yahoo.com/jackson-jury-ends-deliberations-until-tuesday-235030969.html  0013-09-27 09:23:40 | Eric Clapton-owned Richter painting to sell in NYC | http://news.yahoo.com/eric-clapton-owned-richter-painting-sell-nyc-201447252.html  0013-09-27 09:14:15 | Report: Hollywood is less gay-friendly off-screen | http://news.yahoo.com/report-hollywood-less-gay-friendly-off-screen-231415235.html (10 rows)  

CSV

Multicorn может эксплуатировать CSV обложка по образу генератор данных. Как равно на прошлые разы, создаем сервер равным образом таблицу на CSV ресурса:

  # CREATE SERVER csv_srv foreign data wrapper multicorn options (  wrapper 'multicorn.csvfdw.CsvFdw' ); CREATE SERVER # CREATE FOREIGN TABLE csvtest (  sort_order numeric,  common_name character varying,  formal_name character varying,  main_type character varying,  sub_type character varying,  sovereignty character varying,  capital character varying ) server csv_srv options (  filename '/var/data/countrylist.csv',  skip_header '1',  delimiter ','); CREATE FOREIGN TABLE  

Основные опции:

Результат таблицы «csvtest»:

  # SELECT * FROM csvtest LIMIT 00; sort_order | common_name | formal_name | main_type | sub_type | sovereignty | capital ------------+---------------------+-----------------------------------------+-------------------+----------+-------------+------------------  0 | Afghanistan | Islamic State of Afghanistan | Independent State | | | Kabul  0 | Albania | Republic of Albania | Independent State | | | Tirana  0 | Algeria | People's Democratic Republic of Algeria | Independent State | | | Algiers  0 | Andorra | Principality of Andorra | Independent State | | | Andorra la Vella  0 | Angola | Republic of Angola | Independent State | | | Luanda  0 | Antigua and Barbuda | | Independent State | | | Saint John's  0 | Argentina | Argentine Republic | Independent State | | | Buenos Aires  0 | Armenia | Republic of Armenia | Independent State | | | Yerevan  0 | Australia | Commonwealth of Australia | Independent State | | | Canberra  00 | Austria | Republic of Austria | Independent State | | | Vienna (10 rows)  

Другие FDW

Multicorn как и заключает FDW к LDAP равным образом файловой системы. LDAP FDW может применяться чтобы доступа для серверам сообразно LDAP протоколу . FDW к файловой системы может взяться использован на доступа ко данным, хранящимся во различных файлах во файловой системе.

Собственный FDW

Multicorn предоставляет азбучный интерфейс для того написания собственных FDW. Более подробную информацию вам можете раскопать согласно этой ссылке .

PostgreSQL 0.3+

В PostgreSQL 0.1 да 0.2 была представлена отпуск FDW всего возьми чтение. Начиная не без; версии 0.3, FDW может строчить во внешние список источников данных. Сейчас Multicorn поддерживает отметка данных во некоторые источники, начиная со версии 0.0.0.

Заключение

Multicorn — расколачивание пользу кого PostgreSQL, которое позволяет пускать в дело встроенные FDW сиречь формировать собственные для Python.

Pgaudit

Pgaudit  — пополнение в целях PostgreSQL, которое позволяет набирать перипетии изо различных источников в недрах PostgreSQL равно записывает их во формате CSV c временной меткой, информацией по части пользователе, объекте, тот или другой был затронут командой (если такое произошло) равно полным текстом команды. Поддерживает безвыездно DDL, DML (включая SELECT ) равным образом накипь команды. Данное растягивание работает во PostgreSQL 0.3 равным образом выше.

После установки расширения нужно добавит во конфиг PostgreSQL настройки расширения:

  shared_preload_libraries='pgaudit'  pgaudit.log='read, write, user'  

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

  # CREATE EXTENSION pgaudit;  

После сего на логах не грех вкусить близкий итог с pgaudit:

  LOG: [AUDIT],2014-04-30 07:13:55.202854+09,auditdb,ianb,ianb,DEFINITION,CREATE TABLE,TABLE,public.x,CREATE TABLE public.x (a pg_catalog.int4 , b pg_catalog.int4 ) WITH (oids=OFF) LOG: [AUDIT],2014-04-30 07:14:06.548923+09,auditdb,ianb,ianb,WRITE,INSERT,TABLE,public.x,INSERT INTO x VALUES(1,1); LOG: [AUDIT],2014-04-30 07:14:21.221879+09,auditdb,ianb,ianb,READ,SELECT,TABLE,public.x,SELECT * FROM x; LOG: [AUDIT],2014-04-30 07:15:25.620213+09,auditdb,ianb,ianb,READ,SELECT,VIEW,public.v_x,SELECT * from v_x; LOG: [AUDIT],2014-04-30 07:15:25.620262+09,auditdb,ianb,ianb,READ,SELECT,TABLE,public.x,SELECT * from v_x; LOG: [AUDIT],2014-04-30 07:16:00.849868+09,auditdb,ianb,ianb,WRITE,UPDATE,TABLE,public.x,UPDATE x SET a=a+1; LOG: [AUDIT],2014-04-30 07:16:18.291452+09,auditdb,ianb,ianb,ADMIN,VACUUM,,,VACUUM x; LOG: [AUDIT],2014-04-30 07:18:01.08291+09,auditdb,ianb,ianb,DEFINITION,CREATE FUNCTION,FUNCTION,public.func_x(),CREATE FUNCTION public.func_x() RETURNS pg_catalog.int4 LANGUAGE sql VOLATILE CALLED ON NULL INPUT SECURITY INVOKER COST 000.000000 AS $dprs_$SELECT a FROM x LIMIT 0;$dprs_$  

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

Ltree

Ltree  — расширение, которое позволяет сберегать древовидные структуры во виде меток, а вдобавок предоставляет широкие потенциал поиска до ним.

Почему Ltree?

Установка да эксплуатация

Для азы активируем продолжение для того базы данных:

  # CREATE EXTENSION ltree;  

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

  CREATE TABLE comments (user_id integer, description text, path ltree); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0001.0001.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0002.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 01, md5(random()::text), '0001.0003.0002.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0002.0002.0001'); INSERT INTO comments (user_id, description, path) VALUES ( 00, md5(random()::text), '0001.0003.0002.0002.0002'); INSERT INTO comments (user_id, description, path) VALUES ( 01, md5(random()::text), '0001.0003.0002.0002.0003'); INSERT INTO comments (user_id, description, path) VALUES ( 02, md5(random()::text), '0001.0003.0002.0002.0004'); INSERT INTO comments (user_id, description, path) VALUES ( 04, md5(random()::text), '0001.0003.0002.0002.0005'); INSERT INTO comments (user_id, description, path) VALUES ( 02, md5(random()::text), '0001.0003.0002.0002.0006');  

Не забываем подложить индексы:

  # CREATE INDEX path_gist_comments_idx ON comments USING GIST(path); # CREATE INDEX path_comments_idx ON comments USING btree(path);  

В данном примере аз многогрешный создаю таблицу comments из полем path , которое да довольно заключать абсолютный дорога для этому комментарию на дереве (я использую 0 цифры равно точку с целью делителя узлов дерева). Для основные принципы найдем безвыездно комментарии, у которых ход начинается от 0001.0003 :

  # SELECT user_id, path FROM comments WHERE path <@ '0001.0003';  user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0003  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006 (12 rows)  

И проверим равно как работают индексы:

  # SET enable_seqscan=false; SET # EXPLAIN ANALYZE SELECT user_id, path FROM comments WHERE path <@ '0001.0003';  QUERY PLAN -----------------------------------------------------------------------------------------------------------------------------------  Index Scan using path_gist_comments_idx on comments (cost=0.00..8.29 rows=2 width=38) (actual time=0.023..0.034 rows=12 loops=1)  Index Cond: (path <@ '0001.0003'::ltree)  Total runtime: 0.076 ms (3 rows)  

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

  # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*'; user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0003  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006 (12 rows)  

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

  # INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001.0001'); # INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001.0002'); # INSERT INTO comments (user_id, description, path) VALUES ( 0, md5(random()::text), '0001.0003.0001.0003'); # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*'; user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0003  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006  0 | 0001.0003.0001.0001  0 | 0001.0003.0001.0002  0 | 0001.0003.0001.0003 (15 rows) # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*' ORDER by path;  user_id | path ---------+--------------------------  0 | 0001.0003  0 | 0001.0003.0001  0 | 0001.0003.0001.0001  0 | 0001.0003.0001.0002  0 | 0001.0003.0001.0003  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006  0 | 0001.0003.0002.0003 (15 rows)  

Для поиска допускается пустить в дело отличаются как небо и земля модификаторы. Пример использования «или» ( | ):

  # SELECT user_id, path FROM comments WHERE path ~ '0001.*{1,2}.0001|0002.*' ORDER by path;  user_id | path ---------+--------------------------  0 | 0001.0001.0001  0 | 0001.0001.0001.0001  0 | 0001.0001.0001.0002  0 | 0001.0001.0001.0003  0 | 0001.0002.0001  0 | 0001.0003.0001  0 | 0001.0003.0001.0001  0 | 0001.0003.0001.0002  0 | 0001.0003.0001.0003  0 | 0001.0003.0002  01 | 0001.0003.0002.0001  0 | 0001.0003.0002.0002  0 | 0001.0003.0002.0002.0001  00 | 0001.0003.0002.0002.0002  01 | 0001.0003.0002.0002.0003  02 | 0001.0003.0002.0002.0004  04 | 0001.0003.0002.0002.0005  02 | 0001.0003.0002.0002.0006  0 | 0001.0003.0002.0003 (19 rows)  

Например, найдем прямых потомков ото 0001.0003 :

  # SELECT user_id, path FROM comments WHERE path ~ '0001.0003.*{1}' ORDER by path;  user_id | path ---------+----------------  0 | 0001.0003.0001  0 | 0001.0003.0002 (2 rows)  

Можно равным образом выискать родителя про потомица «0001.0003.0002.0002.0005»:

  # SELECT user_id, path FROM comments WHERE path=subpath('0001.0003.0002.0002.0005', 0, -1) ORDER by path;  user_id | path ---------+---------------------  0 | 0001.0003.0002.0002 (1 row)  

Заключение

Ltree — расширение, которое позволяет держать да подходяще ворочать Materialized Path на PostgreSQL.

PostPic

PostPic - распространение ради PostgreSQL, которое позволяет выделывать изображения во базе данных, по образу PostGIS делает сие не без; пространственными данными. Он добавляет недавний будто полина image , а да мало-мальски функций интересах обработки изображений (обрезка краев, генерация миниатюр, заворот да т.д.) да извлечений его атрибутов (размер, тип, разрешение). Более подробнее что до возможностях расширения не грех составить себя представление в официальной странице .

Fuzzystrmatch

Fuzzystrmatch растягивание предоставляет небольшую толику функций про определения сходства равным образом расстояния средь строками. Функция soundex используется с целью согласования тожественно звучащих имен толково преобразования их во равновеликий код. Функция difference преобразует двум строки во soundex код, а впоследствии сообщает численность совпадающих позиций кода. В soundex шифр состоит с четырех символов, следственно произведение склифосовский с нуля предварительно четырех: 0 — безвыгодный совпадают, 0 — точное дублирование (таким образом, цель названа неверно — наравне наименование не чета идет similarity):

  # CREATE EXTENSION fuzzystrmatch; CREATE EXTENSION # SELECT soundex('hello world!');  soundex ---------  H464 (1 row)  # SELECT soundex('Anne'), soundex('Ann'), difference('Anne', 'Ann');  soundex | soundex | difference ---------+---------+------------  A500 | A500 | 0 (1 row)  # SELECT soundex('Anne'), soundex('Andrew'), difference('Anne', 'Andrew');  soundex | soundex | difference ---------+---------+------------  A500 | A536 | 0 (1 row)  # SELECT soundex('Anne'), soundex('Margaret'), difference('Anne', 'Margaret');  soundex | soundex | difference ---------+---------+------------  A500 | M626 | 0 (1 row)  # CREATE TABLE s (nm text); CREATE TABLE # INSERT INTO s VALUES ('john'), ('joan'), ('wobbly'), ('jack'); INSERT 0 0 # SELECT * FROM s WHERE soundex(nm)=soundex('john');  nm ------  john  joan (2 rows)  # SELECT * FROM s WHERE difference(s.nm, 'john') > 0;  nm ------  john  joan  jack (3 rows)  

Функция levenshtein вычисляет протяжённость Левенштейна в ряду двумя строками. levenshtein_less_equal ускоряется функцию levenshtein в целях маленьких значений расстояния:

  # SELECT levenshtein('GUMBO', 'GAMBOL');  levenshtein -------------  0 (1 row)  # SELECT levenshtein('GUMBO', 'GAMBOL', 0, 0, 0);  levenshtein -------------  0 (1 row)  # SELECT levenshtein_less_equal('extensive', 'exhaustive', 0);  levenshtein_less_equal ------------------------  0 (1 row)  test=# SELECT levenshtein_less_equal('extensive', 'exhaustive', 0);  levenshtein_less_equal ------------------------  0 (1 row)  

Функция metaphone , в духе равным образом soundex, построена держи идее создания стих к строки: двум строки, которые будут учитывать похожими, будут совмещать птицы одного полета коды. Последним параметром указывается максимальная долгота metaphone кода. Функция dmetaphone вычисляет двум «как звучит» заключение чтобы строки — «первичный» равно «альтернативный»:

  # SELECT metaphone('GUMBO', 0);  metaphone -----------  KM (1 row) # SELECT dmetaphone('postgresql');  dmetaphone ------------  PSTK (1 row)  # SELECT dmetaphone_alt('postgresql');  dmetaphone_alt ----------------  PSTK (1 row)  

Pg_trgm

Автодополнение  — отправления на программах, предусматривающих диалоговый пуск текста за дополнению текста в соответствии с введённой его части. Реализуется сие простым LIKE "some%" запросом во базу, идеже «some» — то, который читатель успел установить во закраина ввода. Проблема на том, в чем дело? во огромной таблице такого типа требование короче сидеть архи медленно. Для ускорения запроса вроде LIKE "bla%" не запрещается утилизировать text_pattern_ops ради text полина либо — либо varchar_pattern_ops интересах varchar полина сословие операторов на определении индекса (данные типы индексов невыгодный будут делать про стандартных операторов < , <= , => , > равно чтобы работы не без; ними придется образовать всегдашний btree индекс).

  # create table tags ( # tag text primary key, # name text not null, # shortname text, # status char default 'S', # # check( status in ('S', 'R') ) # ); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tags_pkey" for table "tags" CREATE TABLE  # CREATE INDEX i_tag ON tags USING btree(lower(tag) text_pattern_ops); CREATE INDEX  # EXPLAIN ANALYZE select * from tags where lower(tag) LIKE lower('0146%');  QUERY PLAN -----------------------------------------------------------------------------------------------------------------------  Bitmap Heap Scan on tags (cost=5.49..97.75 rows=121 width=26) (actual time=0.025..0.025 rows=1 loops=1)  Filter: (lower(tag) ~~ '0146%'::text)  -> Bitmap Index Scan on i_tag (cost=0.00..5.46 rows=120 width=0) (actual time=0.016..0.016 rows=1 loops=1)  Index Cond: ((lower(tag) ~>=~ '0146'::text) AND (lower(tag) ~<~ '0147'::text))  Total runtime: 0.050 ms (5 rows)  

Для побольше сложных вариантов поиска, таких в качестве кого LIKE "%some%" другими словами LIKE "so%me%" такого склада коэффициент невыгодный короче работать, да эту проблему не грех сделать выбор от расширение.

Pg_trgm  — PostgreSQL расширение, которое предоставляет функции равно операторы пользу кого определения схожести алфавитно-цифровых строк бери основе триграмм, а равным образом классы операторов индексов, поддерживающие стремительный разведка схожих строк. Триграмма — сие категория трёх последовательных символов, взятых с строки. Можно замерить схожесть двух строк, подсчитав количество триграмм, которые снедать во обеих. Эта простая тезис в действительности весть эффективной про измерения схожести слов нате многих естественных языках. Модуль pg_trgm предоставляет классы операторов индексов GiST равным образом GIN, позволяющие формировать числовой показатель соответственно текстовым колонкам ради куда быстрого поиска за критерию схожести. Эти типы индексов поддерживают % да <-> операторы схожести равным образом точный поддерживают разглядывание получай основе триграмм к запросов не без; LIKE , ILIKE , ~ да ~* (эти индексы никак не поддерживают простые операторы сравнения равно равенства, приблизительно почто может нуждаться да привычный btree индекс).

  # CREATE TABLE test_trgm (t text); # CREATE INDEX trgm_idx ON test_trgm USING gist (t gist_trgm_ops); -- or # CREATE INDEX trgm_idx ON test_trgm USING gin (t gin_trgm_ops);  

После создания GIST сиречь GIN индекса по мнению колонке t не возбраняется исполнять разыскание в области схожести. Пример запроса:

  SELECT t, similarity(t, 'word') AS sml  FROM test_trgm  WHERE t % 'word'  ORDER BY sml DESC, t;  

Он выдаст по сию пору значения во текстовой колонке, которые шабаш схожи со одно слово word , во порядке сортировки с в особенности для наименее схожим. Другой разночтение предыдущего запроса (может фигурировать будет действенно выполнен со применением индексов GiST, а малограмотный GIN):

  SELECT t, t <-> 'word' AS dist  FROM test_trgm  ORDER BY dist LIMIT 00;  

Начиная вместе с PostgreSQL 0.1, сии типы индексов тоже поддерживают розыск не без; операторами LIKE равно ILIKE , например:

  SELECT * FROM test_trgm WHERE t LIKE '%foo%bar';  

Начиная из PostgreSQL 0.3, индексы сих типов в свой черед поддерживают сканирование согласно регулярным выражениям (операторы ~ да ~* ), например:

  SELECT * FROM test_trgm WHERE t ~ '(foo|bar)';  

Относительно поиска по мнению регулярному выражению либо — либо от LIKE , нужно брать во расчет, что-нибудь около отсутствии триграмм на искомом шаблоне отыскивание сводится для полному сканирования индекса. Выбор в ряду индексами GiST равно GIN зависит через относительных характеристик производительности GiST равно GIN, которые в этом месте далеко не рассматриваются. Как правило, дефлятор GIN быстрее индекса GiST близ поиске, да строится тож обновляется спирт медленнее; следственно GIN отличается как небо с земли годится для того статических, а GiST для того сплошь и рядом изменяемых данных.

Cstore_fdw

Cstore_fdw расколачивание реализует трафарет хранения данных в базе семейства столбцов (column-oriented systems) для того PostgreSQL (колоночное укрытие данных). Такое выдерживание данных обеспечивает заметные достижения ради аналитических задач ( OLAP , data warehouse ), так как надобно считывать не в таковский мере данных от диска (благодаря формату хранения да компресии). Расширение использует Optimized Row Columnar (ORC) микроформат к размещения данных получи диске, кой имеет следующие преимущества:

Установка равным образом контрафакция

Для работы cstore_fdw нельзя не protobuf-c пользу кого сериализации равно десериализации данных. Далее необходимо прибросить на postgresql.conf расширение:

  shared_preload_libraries='cstore_fdw'  

И активировать его интересах базы:

  # CREATE EXTENSION cstore_fdw;  

Для загрузки данных во cstore таблицы существует двушничек варианта:

Cstore таблицы безвыгодный поддерживают INSERT (кроме раньше упомянутого INSERT INTO ... SELECT ), UPDATE не так — не то DELETE команды.

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

  $ wget http://examples.citusdata.com/customer_reviews_1998.csv.gz $ wget http://examples.citusdata.com/customer_reviews_1999.csv.gz  $ gzip -d customer_reviews_1998.csv.gz $ gzip -d customer_reviews_1999.csv.gz  

Далее загрузим сии эмпирика во cstore таблицу (расширение уж активировано для того PostgreSQL):

  -- create server object CREATE SERVER cstore_server FOREIGN DATA WRAPPER cstore_fdw;  -- create foreign table CREATE FOREIGN TABLE customer_reviews (  customer_id TEXT,  review_date DATE,  review_rating INTEGER,  review_votes INTEGER,  review_helpful_votes INTEGER,  product_id CHAR(10),  product_title TEXT,  product_sales_rank BIGINT,  product_group TEXT,  product_category TEXT,  product_subcategory TEXT,  similar_product_ids CHAR(10)[] ) SERVER cstore_server OPTIONS(compression 'pglz');  COPY customer_reviews FROM '/tmp/customer_reviews_1998.csv' WITH CSV; COPY customer_reviews FROM '/tmp/customer_reviews_1999.csv' WITH CSV;  ANALYZE customer_reviews;  

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

  -- Find all reviews a particular customer made on the Dune series in 0998. # SELECT  customer_id, review_date, review_rating, product_id, product_title FROM  customer_reviews WHERE  customer_id='A27T7HVDXA3K2A' AND  product_title LIKE '%Dune%' AND  review_date >='1998-01-01' AND  review_date <='1998-12-31';  customer_id | review_date | review_rating | product_id | product_title ----------------+-------------+---------------+------------+-----------------------------------------------  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0399128964 | Dune (Dune Chronicles (Econo-Clad Hardcover))  A27T7HVDXA3K2A | 0998-04-10 | 0 | 044100590X | Dune  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0441172717 | Dune (Dune Chronicles, Book 0)  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0881036366 | Dune (Dune Chronicles (Econo-Clad Hardcover))  A27T7HVDXA3K2A | 0998-04-10 | 0 | 0559949570 | Dune Audio Collection (5 rows)  Time: 038.626 ms  -- Do we have a correlation between a book's title's length and its review ratings? # SELECT  width_bucket(length(product_title), 0, 00, 0) title_length_bucket,  round(avg(review_rating), 0) AS review_average,  count(*) FROM  customer_reviews WHERE  product_group='Book' GROUP BY  title_length_bucket ORDER BY  title_length_bucket;  title_length_bucket | review_average | count ---------------------+----------------+--------  0 | 0.26 | 039034  0 | 0.24 | 011318  0 | 0.34 | 045671  0 | 0.32 | 067361  0 | 0.30 | 018422  0 | 0.40 | 016412 (6 rows)  Time: 0285.059 ms  

Заключение

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

Postgresql-hll

На теперешний с утра до ночи свободно распространена урок подсчета количества уникальных элементов (count-distinct problem) во потоке данных, которые могут кормить повторяющиеся элементы. Например, насколько уникальных IP-адресов подключалось для серверу ради свежий час? Сколько различных слов во большом куске текстов? Какое величина уникальных посетителей побывало получи и распишись популярном сайте ради день? Сколько уникальных URL было запрошено сквозь прокси-сервер? Данную задачу позволительно принять решение «в лоб»: пробежать по мнению во всех отношениях элементам да спрятать дубликаты, позже сего счесть их доля (например эксплуатнуть множество, set). Трудности на таком подходе возникают подле увеличении масштаба. С минимальными затратами позволяется пересчитать тысячу сиречь аж мильон уникальных посетителей, IP-адресов, URL сиречь слов. А аюшки? буде говорок по рукам что касается 000 миллионах уникальных элементов бери сам в соответствии с себе сервер подле наличии тысяч серверов? Теперь сие сейчас становится интересным.

Текущее заключение проблемы полноте облюбовать так: никуда не денешься выковать множества (set) уникальных элементов с целью каждого с 0000 серверов, каждое изо которых может таить в себе рядом 000 миллионов уникальных элементов, а по времени подвести итог состав уникальных элементов во объединении сих множеств. Другими словами, автор имеем деяние от распределенным вариантом задачи подсчета уникальных элементов. Хоть сие намерение является основательно логичным, для практике таковой аспект обойдется высокой ценой. Для примера возьмем URL, средняя метраж которого составляет 06 символов. В нашем случае сам в соответствии с себе сервер обслуживает близ 000 миллионов уникальных URL, следовательно, размер файла от их перечнем составит возле 0.6 ГБ. Даже коли и оный и другой URL переустроить во 04-битный хеш, размер файла составит 000 МБ. Это гораздо лучше, так безграмотный забывайте, аюшки? выговор пусть будет так касательно 0000 серверов. Каждый сервер отправляет обложка вместе с перечнем уникальных URL нате коренной сервер, следовательно, подле наличии 0000 серверов круг обязанностей объединения множеств должна пройти 000 ГБ данных. Если такая деятельность должна облекаться в мясо и кровь часто, позднее надлежит короче либо назначить систему с целью обработки больших данных (и рекрутировать команду интересах ее обслуживания), либо выискать другое решение.

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

Вспомним пока что одно базовое место теории вероятностей, согласие которому ожидаемое состав испытаний, необходимое с целью наступления события, вычисляется по части формуле $1/P(event)$ . Следовательно, буде $P(one\ specific\ bit\ set)=50\%$ , в таком случае ожидаемое величина испытаний равняется 0. Для двух битов — 0, для того трех битов — 0 да т.д.

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

Рассмотрим алгорифм подробно. Вначале ничего не поделаешь хешировать до этого времени азбука исследуемого набора. Затем нужно подбить бабки состав последовательных начальных битов, равных единице, на двоичном представлении каждого хеша равно установить максимальное сила сего количества середь всех хешей. Если максимальное величина единиц пометить $n$ , в таком разе часть уникальных элементов на наборе позволено оценить, равно как $2^n$ . То есть, неравно не более единственный первый двоичный знак равен единице, тут доля уникальных элементов, во среднем, в одинаковой мере 0; коли самое многое три начальных битка равны единице, на среднем, да мы из тобой можем надеяться 0 уникальных элементов да т.д.

Подход, повергнутый держи увеличение точности оценки да являющийся одной изо ключевых идей HyperLogLog, заключается во следующем: разделяем хеши в подгруппы получи и распишись основании их конечных битов, определяем максимальное цифра начальных единиц во каждой подгруппе, а впоследствии находим среднее. Этот подступ позволяет произвести заметно больше точную оценку общего количества уникальных элементов. Если автор сих строк имеем $m$ подгрупп равным образом $n$ уникальных элементов, тогда, на среднем, во каждой подгруппе хорошенького понемножку $n/m$ уникальных элементов. Таким образом, присутствие среднего в области во всем подгруппам дает стоит точную оценку величины $log_2{(n/m)}$ , а от сего места легко и просто позволено произвести необходимое нам значение. Более того, HyperLogLog позволяет убеждать сообразно отдельности небо и земля варианты группировок, а впоследствии в основе сих данных отыскивать итоговую оценку. Следует отметить, что-то для того нахождения среднего HyperLogLog использует среднее гармоническое, которое обеспечивает избранные результаты в области сравнению со средним арифметическим (более подробную информацию дозволительно сыскать на оригинальных публикациях, посвященных LogLog равно HyperLogLog ).

Вернемся ко задаче. По условию существует 0000 серверов да 000 миллионов уникальных URL в произвольный сервер, следовательно, главнейший сервер потребно подвергать обработке 000 ГБ данных подле каждом выполнении простого варианта алгоритма. Это как и означает, почто 000 ГБ данных произвольный присест надлежит посылать по мнению сети. HyperLogLog меняет ситуацию кардинально. Согласно анализу, проведенному авторами оригинальной публикации, HyperLogLog обеспечивает определённость вблизи 08% возле использовании токмо 0.5 КБ памяти. Каждый сервер формирует согласующий обложка размером 0.5 КБ, а дальше отправляет его нате ключевой сервер. При наличии 0000 серверов, главнейший сервер обрабатывает лишь 0.5 МБ данных присутствие каждом выполнении алгоритма. Другими словами, обрабатывается как только 0.0002% данных до сравнению не без; предыдущим решением. Это без остатка меняет экономичный мнение задачи. Благодаря HyperLogLog, как ми видится реализовывать такие операции чаще да во большем количестве. И весь сие ценой просто-напросто всего только 0% погрешности.

Для работы от сим алгоритмом в середине PostgreSQL было создано увеличение postgresql-hll . Оно добавляет свежий субъект полина hll , некоторый представляет собою HyperLogLog структуру данных. Рассмотрим образчик его использования.

Установка да контрафакция

Для основы инициализируем растягивание во базе данных:

  # CREATE EXTENSION hll;  

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

  CREATE TABLE users_visits (  date date,  user_id integer,  activity_type smallint,  referrer varchar(255) );  

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

  CREATE TABLE daily_uniques (  date date UNIQUE,  users hll );  -- Fill it with the aggregated unique statistics INSERT INTO daily_uniques(date, users)  SELECT date, hll_add_agg(hll_hash_integer(user_id))  FROM users_visits  GROUP BY 0;  

Далее хэшируется user_id да собираются сии хэш-значения во одинокий hll следовать день. Теперь дозволено заломить цену информацию объединение уникальным пользователям следовать произвольный день:

  # SELECT date, hll_cardinality(users) FROM daily_uniques;  date | hll_cardinality ------------+-----------------  0017-02-21 | 03123  0017-02-22 | 09433  0017-02-23 | 0134890  0017-02-24 | 0276247 (4 rows)  

Можно возразить, аюшки? такую задачу позволяется замыслить равно чрез COUNT DISTINCT равно сие полноте верно. Но на примере исключительно ответили бери вопрос: «Сколько уникальных пользователей посещает сайт первый попавшийся день?». А что, неравно нельзя не вкушать сколечко уникальных пользователей посетили сайт ради неделю?

  SELECT hll_cardinality(hll_union_agg(users)) FROM daily_uniques WHERE date >='2017-02-20'::date AND date <='2017-02-26'::date;  

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

  SELECT EXTRACT(MONTH FROM date) AS month, hll_cardinality(hll_union_agg(users)) FROM daily_uniques WHERE date >='2016-01-01' AND  date < '2017-01-01' GROUP BY 0;  

Или распознать контингент пользователей, который посетили сайт вчера, так далеко не сегодня?

  SELECT date, (#hll_union_agg(users) OVER two_days) - #users AS lost_uniques FROM daily_uniques WINDOW two_days AS (ORDER BY date ASC ROWS 0 PRECEDING);  

Это лишь чета примеров типов запросов, которые будут возвращать произведение во ход миллисекунд по причине hll , однако потребует либо совершенно отдельные вперед созданные агрегирующие таблицы или — или self join/generate_series вычуры во COUNT DISTINCT мире.

Заключение

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

Tsearch2

Как да многие современные СУБД, PostgreSQL имеет замонтированный устройство полнотекстового поиска. Отметим, что-то операторы поиска в соответствии с текстовым данных существовали бог давно, сие операторы LIKE , ILIKE , ~ , ~* . Однако, они невыгодный годились чтобы эффективного полнотекстового поиска, круглым счетом как:

Для улучшения ситуации священный Бартунов равным образом Федор Сигаев предложили да реализовали новоявленный полнотекстовый поиск, существовавший в духе узел расширения равным образом интегрированный на PostgreSQL, начиная из версии 0.3 — Tsearch2 .

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

PostgreSQL предоставляет случай наравне в целях создания новых типов данных, операторов, беспричинно да создания индексной поддержки в целях доступа ко ним, притом вместе с поддержкой конкурентности да восстановления позже сбоев. Однако, нужно понимать, ась? индексы нужны лишь только в целях ускорения поиска, своевольно подыскание обязан трудиться да не принимая во внимание них. Таким образом, были созданы новые типы данных - tsvector , кой является хранилищем ради лексем изо документа, оптимизированного для того поиска, да tsquery - ради запроса вместе с поддержкой логических операций, полнотекстовый команда «две собаки» @@ равным образом индексная помощь для того него не без; использованием GiST да GIN. tsvector не беря в расчет самих лексем может экономить информацию по отношению положении лексемы на документе равным образом ее весе (важности), которая затем может употребляться с целью прикидки ранжирующей информации.

Установка равно утилизация

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

  # CREATE EXTENSION tsearch2;  

Проверим его работу:

  # SELECT 'This is test string'::tsvector;  tsvector -----------------------------  'This' 'is' 'string' 'test' (1 row)  # SELECT strip(to_tsvector('The air smells of sea water.'));  strip -----------------------------  'air' 'sea' 'smell' 'water' (1 row)  

Заключение

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

PL/Proxy

PL/Proxy представляет собою прокси-язык интересах удаленного вызова процедур равно партицирования данных в ряду разными базами (шардинг). Подробнее не возбраняется обожать во «[sec:plproxy] » главе.

Texcaller

Texcaller  — сие сподручный интерфейс в целях командной строки TeX , что обрабатывает постоянно ожидание ошибок. Он написан во простом C, конец легкий равно невыгодный имеет внешних зависимостей, в дополнение TeX. Неверный TeX деловая бумага обрабатывается через простого возвращения NULL, а далеко не прерывается вместе с ошибкой. В случае неудачи, а в свою очередь во случае успеха, дополнительная изготовление информации осуществляется путем NOTICEs.

Pgmemcache

Pgmemcache  — сие PostgreSQL API книгохранилище бери основе libmemcached на взаимодействия вместе с memcached. С через данной библиотеки PostgreSQL может записывать, считывать, разыскивать да долой материал изо memcached. Подробнее позволяется сподобить во «[sec:pgmemcache] » главе.

Prefix

Prefix реализует отыскивание текста соответственно префиксу ( prefix @> text ). Prefix используется на приложениях телефонии, идеже маршрутизация вызовов да издержки зависят через вызывающего/вызываемого префикса телефонного подворье оператора.

Установка да эксплуатация

Для вводные положения инициализируем увеличение во базе данных:

  # CREATE EXTENSION prefix;  

После сего можем проверить, ась? продолжение функционирует:

  # select '123'::prefix_range @> '123456';  ?column? ----------  t (1 row)  # select a, b, a | b as union, a & b as intersect  from (select a::prefix_range, b::prefix_range  from (values('123', '123'),  ('123', '124'),  ('123', '123[4-5]'),  ('123[4-5]', '123[2-7]'),  ('123', '[2-3]')) as t(a, b)  ) as x;   a | b | union | intersect ----------+----------+----------+-----------  023 | 023 | 023 | 023  023 | 024 | 02[3-4] |  023 | 023[4-5] | 023 | 023[4-5]  023[4-5] | 023[2-7] | 023[2-7] | 023[4-5]  023 | [2-3] | [1-3] | (5 rows)  

В примере [lst:pgprefixexample2] производится сканирование мобильного оператора согласно номеру телефона:

  $ wget https://github.com/dimitri/prefix/raw/master/prefixes.fr.csv $ psql  # create table prefixes (  prefix prefix_range primary key,  name text not null,  shortname text,  status char default 'S',   check( status in ('S', 'R') ) ); CREATE TABLE # comment on column prefixes.status is 'S: - R: reserved'; COMMENT # \copy prefixes from 'prefixes.fr.csv' with delimiter ';' csv quote '"' COPY 01966 # create index idx_prefix on prefixes using gist(prefix); CREATE INDEX # select * from prefixes limit 00;  prefix | name | shortname | status --------+------------------------------------------------------------+-----------+--------  010001 | COLT TELECOMMUNICATIONS FRANCE | COLT | S  010002 | EQUANT France | EQFR | S  010003 | NUMERICABLE | NURC | S  010004 | PROSODIE | PROS | S  010005 | INTERNATIONAL TELECOMMUNICATION NETWORK France (Vivaction) | ITNF | S  010006 | SOCIETE FRANCAISE DU RADIOTELEPHONE | SFR | S  010007 | SOCIETE FRANCAISE DU RADIOTELEPHONE | SFR | S  010008 | BJT PARTNERS | BJTP | S  010009 | LONG PHONE | LGPH | S  010010 | IPNOTIC TELECOM | TLNW | S (10 rows)  # select * from prefixes where prefix @> '0146640123';  prefix | name | shortname | status --------+----------------+-----------+--------  0146 | FRANCE TELECOM | FRTE | S (1 row)  # select * from prefixes where prefix @> '0100091234';  prefix | name | shortname | status --------+------------+-----------+--------  010009 | LONG PHONE | LGPH | S (1 row)  

Заключение

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

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

Установка да исчерпывание

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

  # CREATE EXTENSION dblink;  

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

  # SELECT dblink_connect('slave_db', 'host=slave.example.com port=5432 dbname=exampledb user=admin password=password');  dblink_connect ----------------  OK (1 row)  

При успешном выполнении команды хорэ выведен опровержение «OK». Теперь не возбраняется испробовать вычислять факты изо таблиц при помощи dblink функцию:

  # SELECT * FROM dblink('slave_db', 'SELECT id, username FROM users LIMIT 0') AS dblink_users(id integer, username text);   id | username ----+----------------------------------  0 | 04ec7083d7facb7c5d97684e7f415b65  0 | 004c3b639a920b5ba814fc01353368f2  0 | 053041f992e3eab6891f0e8da9d11f23 (3 rows)  

По завершению работы вместе с сервером, подсоединение надлежит локаутировать при помощи функцию dblink_disconnect :

  # SELECT dblink_disconnect('slave_db');  dblink_disconnect -------------------  OK (1 row)  

Курсоры

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

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

  # SELECT dblink_open('slave_db', 'users', 'SELECT id, username FROM users');  dblink_open -------------  OK (1 row)  

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

  # SELECT id, username FROM dblink_fetch('slave_db', 'users', 0) AS (id integer, username text);  id | username ----+----------------------------------  0 | 04ec7083d7facb7c5d97684e7f415b65  0 | 004c3b639a920b5ba814fc01353368f2 (2 rows)  # SELECT id, username FROM dblink_fetch('slave_db', 'users', 0) AS (id integer, username text);  id | username ----+----------------------------------  0 | 053041f992e3eab6891f0e8da9d11f23  0 | 018c33458b4840f90d87ee4ea8737515 (2 rows)  # SELECT id, username FROM dblink_fetch('slave_db', 'users', 0) AS (id integer, username text);  id | username ----+----------------------------------  0 | 0b795b0e73b00220843f82c4d0f81f37  0 | c2673ee986c23f62aaeb669c32261402 (2 rows)  

После работы от курсором его нужно непременно застлать помощью dblink_close функцию:

  # SELECT dblink_close('slave_db', 'users');  dblink_close --------------  OK (1 row)  

Асинхронные требования

Последним вариантом пользу кого выполнения запросов во dblink является асинхроичный запрос. При его использовании результаты далеко не будут возвращены предварительно полного выполнения результата запроса. Для создания асинхронного запроса используется dblink_send_query функция:

  # SELECT * FROM dblink_send_query('slave_db', 'SELECT id, username FROM users') AS users;  users -------  0 (1 row)  

Результат стало быть чрез dblink_get_result функцию:

  # SELECT id, username FROM dblink_get_result('slave_db') AS (id integer, username text);  id | username ------+----------------------------------  0 | 04ec7083d7facb7c5d97684e7f415b65  0 | 004c3b639a920b5ba814fc01353368f2  0 | 053041f992e3eab6891f0e8da9d11f23  0 | 018c33458b4840f90d87ee4ea8737515  0 | 0b795b0e73b00220843f82c4d0f81f37  0 | c2673ee986c23f62aaeb669c32261402  0 | c53f14040fef954cd6e73b9aa2e31d0e  00 | 0dbe27fd96cdb39f01ce115cf3c2a517  

Postgres_fdw

Postgres_fdw  — расширение, которое позволяет влить PostgreSQL для PostgreSQL, которые могут разыскиваться возьми разных хостах.

Установка равно эксплуатация

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

  # CREATE EXTENSION postgres_fdw;  

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

  # CREATE SERVER slave_db FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'slave.example.com', dbname 'exampledb', port '5432');  

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

  # CREATE USER MAPPING FOR admin SERVER slave_db OPTIONS (user 'admin', password 'password');  

Теперь дозволительно ввезти таблицы:

  # CREATE FOREIGN TABLE fdw_users (  id serial,  username text not null,  password text,  created_on timestamptz not null,  last_logged_on timestamptz not null ) SERVER slave_db OPTIONS (schema_name 'public', table_name 'users');  

Для того, в надежде безграмотный ввозить каждую таблицу отдельно, не возбраняется прибегнуть IMPORT FOREIGN SCHEMA командой:

  # IMPORT FOREIGN SCHEMA public LIMIT TO (users, pages) FROM SERVER slave_db INTO fdw;  

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

  # SELECT * FROM fdw_users LIMIT 0; -[ RECORD 0 ]--+--------------------------------- id | 0 username | 04ec7083d7facb7c5d97684e7f415b65 password | b82af3966b49c9ef0f7829107db642bc created_on | 0017-02-21 05:07:25.619561+00 last_logged_on | 0017-02-19 01:03:35.651561+00  

По умолчанию с таблиц дозволено неграмотный всего лишь читать, да да доносить на них способности ( INSERT/UPDATE/DELETE ). updatable опция может пустить в дело про подключения ко серверу на режиме «только бери чтение»:

  # ALTER SERVER slave_db OPTIONS (ADD updatable 'false'); ALTER SERVER # DELETE FROM fdw_users WHERE id < 00; ERROR: foreign table "fdw_users" does not allow deletes  

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

  # ALTER FOREIGN TABLE fdw_users OPTIONS (ADD updatable 'false');  

Как дозволено было заметить, postgres_fdw да dblink выполняют одну равным образом ту но работу — включение одной PostgreSQL базы для другой. Что паче пускать в дело во таком случае?

PostgreSQL FDW (Foreign Data Wrapper) больше новоизобретённый равно рекомендуемый рецепт подключения ко другим источникам данных. Хотя функциональность dblink похожа сверху FDW, концевой является побольше SQL совместимым равно может обезопасить улучшеную полезный эффект сообразно сравнению со dblink подключениями. Кроме того, во отличии ото postgres_fdw, dblink безвыгодный ловок учинить материал «только держи чтение». Это может состоять порядочно важно, разве приходится обеспечить, с намерением исходняк на иной базе запрещается было изменять.

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

Из положительных сторон dblink не грех отнести пропасть полезных комманд, которые позволяют утилизировать его с целью программирования полезного функционала. Также dblink работает на версиях PostgreSQL 0.3 равным образом выше, во в таком случае срок на правах postgres_fdw работает только лишь во PostgreSQL 0.3 равным образом превыше (такое может возникнуть, разве не имеется потенциал дать новую жизнь PostgreSQL базу).

Pg_cron

Pg_cron  — cron-подобный откосопланировщик задач пользу кого PostgreSQL 0.5 тож выше, тот или другой работает в качестве кого увеличение ко базе. Он может проводить в жизнь до некоторой степени задач параллельно, да сразу может коптеть неграмотный паче одного экземпляра задания (если подле запуске задачи прежний запускание склифосовский до этих пор выполняться, так запускание хорошенького понемножку отложен поперед выполнения текущей задачи).

Установка равно эксплуатация

После установки расширения надлежит приплюсовать его во postgresql.conf да перезапустить PostgreSQL:

  shared_preload_libraries='pg_cron'  

Далее надо активировать развертывание в целях postgres базы:

  # CREATE EXTENSION pg_cron;  

По умолчанию pg_cron ожидает, который однако таблицы из метаданными будут отираться во postgres базе данных. Данное аллопрининг не возбраняется поменять равно выделить посредством параметр cron.database_name во postgresql.conf другую базу данных, идеже pg_cron хорошенького понемножку экономить близкие данные.

Внутри pg_cron использует libpq библиотеку, оттого потребуется дозволить подключения вместе с localhost не принимая во внимание пароля ( trust во pg_hba.conf ) или — или но образовать .pgpass обложка чтобы настройки подключения ко базе.

Для создания cron задач используется деятельность cron.schedule :

  -- Delete old data on Saturday at 0:30am (GMT) SELECT cron.schedule('30 0 * * 0', $$DELETE FROM events WHERE event_time < now() - interval '1 week'$$);  schedule ----------  02  

Для удаления созданых задач используется cron.unschedule :

  -- Vacuum every day at 00:00am (GMT)  SELECT cron.schedule('0 00 * * *', 'VACUUM');  schedule  ----------  03  -- Stop scheduling a job SELECT cron.unschedule(43);  unschedule ------------  t  

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

Поскольку pg_cron использует libpq библиотеку, сие позволят швырять cron задачи получи и распишись других базах данных (даже сверху других серверах). С через суперпользователя что перелицевать cron.job таблицу равным образом наболтать на нее мера подключения ко другой породы базе помощью nodename равно nodeport поля:

  INSERT INTO cron.job (schedule, command, nodename, nodeport, database, username)  VALUES ('0 0 * * *', 'VACUUM', 'worker-node-1', 0432, 'postgres', 'marco');  

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

PGStrom

PGStrom  — PostgreSQL расширение, которое позволяет пускать в дело GPU пользу кого выполнения некоторых SQL операций. В частности, ради счёт привлечения GPU могут взяться ускорены такие операции вроде компаративный перегиб элементов таблиц, агрегирование записей равно фузия хэшей. Код в целях выполнения получи стороне GPU генерируется на время разбора SQL-запроса около помощи специального JIT-компилятора равным образом во дальнейшем выполняется наплевать от другими связанными не без; текущим запросом операциями, выполняемыми в CPU. Для выполнения заданий получай GPU задействован OpenCL. Увеличение производительности операций слияния таблиц ( JOIN ) рядом использовании GPU увеличивается во десятки раз.

Областью применения PG-Strom являются огромные отчеты не без; использованием агрегации равно объединения таблиц. Эти рабочий класс нагрузки чаще используются во пакетной обработке данных ради OLAP систем.

ZomboDB

ZomboDB  — PostgreSQL расширение, которое позволяет эксплуатнуть Elasticsearch индексы в утробе базы (используется интерфейс интересах методов доступа индекса ). ZomboDB коэффициент пользу кого PostgreSQL вничью малограмотный отличается с стандартного btree индекса. Таким образом, стандартные команды SQL целиком поддерживаются, в книга числе и SELECT , BEGIN , COMMIT , ABORT , INSERT , UPDATE , DELETE , COPY равным образом VACUUM да факты индексы являются MVCC-безопасными.

На низком уровне ZomboDB индексы взаимодействуют со Elasticsearch сервером посредством HTTP требования равным образом автопилотом синхронизируются во процессе изменения данных во PostgreSQL базе.

Установка да утилизация

ZomboDB состоит с двух частей: PostgreSQL расширения (написан получи и распишись C да SQL/PLPGSQL) равным образом Elasticsearch плагина (написан получи Java).

После установки надлежит прирастить на postgresql.conf zombodb библиотеку:

  local_preload_libraries='zombodb.so'  

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

  CREATE EXTENSION zombodb;  

После сего надлежит учредить Elasticsearch плагин бери до этого времени ноды сервера равно видоизменить конфигурацию во elasticsearch.yml :

  threadpool.bulk.queue_size: 0024 threadpool.bulk.size: 02  http.compression: true  http.max_content_length: 0024mb index.query.bool.max_clause_count: 0000000  

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

  # CREATE TABLE products (  id SERIAL8 NOT NULL PRIMARY KEY,  name text NOT NULL,  keywords varchar(64)[],  short_summary phrase,  long_description fulltext,  price bigint,  inventory_count integer,  discontinued boolean default false,  availability_date date );  # COPY products FROM PROGRAM 'curl https://raw.githubusercontent.com/zombodb/zombodb/master/TUTORIAL-data.dmp';  

zdb(record) zombodb выражение конвертирует отметка во JSON мера (обертка через row_to_json(record) ):

  # SELECT zdb(products) FROM products WHERE id=1;  zdb ------------------------------------------------- {"id":1,"name":"Magical Widget","keywords":["magical","widget","round"],"short_summary":"A widget that is quite magical","long_description":"Magical Widgets come from the land of Magicville and are capable of things you can't imagine","price":9900,"inventory_count":42,"discontinued":false,"availability_date":"2015-08-31"}  

zdb(regclass, tid) zombodb функция, которая используется в целях статического определения ссылок в таблицу/индекс во контексте последовательного сканирования. Благодаря сим две функциям дозволено учредить zombodb указатель в целях products таблицы:

  # CREATE INDEX idx_zdb_products  ON products  USING zombodb(zdb('products', products.ctid), zdb(products))  WITH (url='http://localhost:9200/');  

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

  # SELECT id, name, short_summary FROM products WHERE zdb('products', products.ctid)==> 'sports or box';  id | name | short_summary ----+----------+--------------------------------  0 | Baseball | It's a baseball  0 | Box | Just an empty box made of wood (2 rows) # EXPLAIN SELECT * FROM products WHERE zdb('products', ctid)==> 'sports or box';  QUERY PLAN -----------------------------------------------------------------------------------  Index Scan using idx_zdb_products on products (cost=0.00..4.02 rows=2 width=153)  Index Cond: (zdb('products'::regclass, ctid)==> 'sports or box'::text) (2 rows)  

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

  # SELECT * FROM zdb_tally('products', 'keywords', '^.*', '', 0000, 'term');  term | count -----------------------+-------  alexander graham bell | 0  baseball | 0  box | 0  communication | 0  magical | 0  negative space | 0  primitive | 0  round | 0  sports | 0  square | 0  widget | 0  wooden | 0 (12 rows)  

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

Заключение

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

Бэкап да воссоздание PostgreSQL

Введение

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

Тоже самое касается равным образом PostgreSQL баз данных. Посыпавшийся винчестер в сервере, неловкость на файловой системе, неловкость во остальной программе, которая перетерла огульно список PostgreSQL равным образом многое другое приведет всего ко плачевному результату. И аж разве у Вас повторение от множеством слейвов, сие малограмотный означает, зачем доктрина во безопасности — слабый просьба сверху знаток ( DELETE/DROP/TRUNCATE ), равно у слейвов такая но рацион данных (точнее их отсутствие).

Существуют три принципиально различных подхода для резервному копированию данных PostgreSQL:

Каждый изо сих подходов имеет приманка сильные равным образом слабые стороны.

SQL бэкап

Идея сего подхода во создании текстового файла вместе с командами SQL. Такой обложка позволено отдать назад возьми сервер равно воскресить базу данных на фолиант а состоянии, во котором симпатия была нет слов промежуток времени бэкапа. У PostgreSQL с целью сего очищать специальная утилита — pg_dump . Пример использования pg_dump :

  $ pg_dump dbname > outfile  

Для восстановления такого бэкапа шабаш выполнить:

  $ psql dbname < infile  

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

  $ psql --set ON_ERROR_STOP=on dbname < infile  

Также, дозволено свершать бэкап да зараз восстанавливать его во другую базу:

  $ pg_dump -h host1 dbname | psql -h host2 dbname  

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

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

  $ pg_dumpall > outfile  

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

  $ psql -f infile postgres  

SQL бэкап больших баз данных

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

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

Бэкап уровня файловой системы

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

  $ tar -cf backup.tar /usr/local/pgsql/data  

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

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

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

Непрерывное резервное переснятие

PostgreSQL поддерживает упреждающую фанера логов (Write Ahead Log, WAL) во pg_xlog директорию, которая находится во директории данных СУБД. В логи пишутся всё-таки изменения, сделанные вместе с данными на СУБД. Этот кондуит существует вовремя токмо пользу кого безопасности изумительный срок краха PostgreSQL: разве происходят сбои на системе, базы данных могут состоять восстановлены вместе с через «перезапуска» сего журнала. Тем отнюдь не менее, жизнь журнала делает возможным оборот третьей стратегии чтобы резервного копирования баз данных: автор сих строк можем спаять бэкап уровня файловой системы не без; резервной копией WAL файлов. Если приходится реанимировать этакий бэкап, в таком случае автор сих строк восстанавливаем файлы резервной копии файловой системы, а а там «перезапускаем» не без; резервной копии файлов WAL про приведения системы для актуальному состоянию. Этот путь является больше сложным пользу кого администрирования, нежели кому всего-навсего не лень изо предыдущих подходов, же симпатия имеет кой-какие преимущества:

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

Настройка

Первый шаг — активировать архивирование. Эта процесс достаточно размножать WAL файлы на архивный синопсис с стандартного каталога pg_xlog . Это делается во файле postgresql.conf :

  archive_mode=on # enable archiving archive_command='cp -v %p /data/pgsql/archives/%f' archive_timeout=300 # timeout to close buffers  

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

  $ rsync -avz --delete prod1:/data/pgsql/archives/ \ /data/pgsql/archives/ > /dev/null  

В конце нельзя не переснять файлы во регистр pg_xlog в сервере PostgreSQL (он потребно являться на режиме восстановления). Для сего никуда не денешься на каталоге данных PostgreSQL разработать обложка recovery.conf вместе с заданной командой копирования файлов с архива на нужную директорию:

  restore_command='cp /data/pgsql/archives/%f "%p"'  

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

Утилиты на непрерывного резервного копирования

Непрерывное резервное копирования - единственный с лучших способов на создания бэкапов равно их восстановления. Нередко бэкапы сохраняются возьми праздник но файловой системе, для которой расположена хранилище данных. Это далеко не адски безопасно, т.к. близ выходе дисковой системы сервера изо строя ваш брат можете утерять целое показатели (и базу, равным образом бэкапы), либо — либо так-таки встретить не без; тем, аюшки? в жестком диске закончится свободное место. Поэтому лучше, рано или поздно бэкапы складываются в один сервер иначе говоря на «облачное хранилище» (например AWS S3 ). Чтобы безграмотный чиркать нестандартный «велосипед» ради автоматизации сего процесса получи и распишись современный воскресенье существует пакет программ, которые облегчают течение настройки равным образом поддержки процесса создания бэкапов сверху основе непрерывного резервного копирования.

WAL-E

WAL-E предназначена к непрерывной архивации PostgreSQL WAL-logs во Amazon S3 либо — либо Windows Azure (начиная вместе с версии 0.7) да управления использованием pg_start_backup равным образом pg_stop_backup . Утилита написана получи и распишись Python да разработана на компании Heroku , идеже её деятельно используют.

Установка

У WAL-E лакомиться брат зависимостей: lzop , psql , pv (в старых версиях используется mbuffer ), python 0.4+ равным образом ряд python библиотек ( gevent , boto , azure ). Также в целях комфорт настроек переменных среды устанавливается daemontools . На Ubuntu сие дозволительно безвыездно сделать одной командой:

  $ aptitude install git-core python-dev python-setuptools python-pip build-essential libevent-dev lzop pv daemontools daemontools-run  

Теперь установим WAL-E:

  $ pip install https://github.com/wal-e/wal-e/archive/v1.0.3.tar.gz  

После успешной установки позволено пофигарить мучиться из WAL-E.

Настройка да разработка

Как уж писалось, WAL-E сливает постоянно документация на AWS S3, почему нам потребуются «Access Key ID», «Secret Access Key» равно «AWS Region» (эти эмпирика позволено откопать на акаунте Amazon AWS). Команда на загрузки бэкапа всей базы данных на S3:

  AWS_REGION=... AWS_SECRET_ACCESS_KEY=... wal-e \  -k AWS_ACCESS_KEY_ID \  --s3-prefix=s3://some-bucket/directory/or/whatever \  backup-push /var/lib/postgresql/9.2/main  

Где s3-prefix  — URL, который-нибудь включает прозвание S3 бакета (bucket) да линия для папке, несравнимо должно упаковывать резервные копии. Команда с целью загрузки WAL-логов возьми S3:

  AWS_REGION=... AWS_SECRET_ACCESS_KEY=... wal-e \  -k AWS_ACCESS_KEY_ID \  --s3-prefix=s3://some-bucket/directory/or/whatever \  wal-push /var/lib/postgresql/9.2/main/pg_xlog/WAL_SEGMENT_LONG_HEX  

Для управления этими переменными окружения позволительно пустить в ход команду envdir (идет во поставке из daemontools ). Для сего создадим envdir каталог:

  $ mkdir -p /etc/wal-e.d/env $ echo "aws_region" > /etc/wal-e.d/env/AWS_REGION $ echo "secret-key" > /etc/wal-e.d/env/AWS_SECRET_ACCESS_KEY $ echo "access-key" > /etc/wal-e.d/env/AWS_ACCESS_KEY_ID $ echo 's3://some-bucket/directory/or/whatever' > /etc/wal-e.d/env/WALE_S3_PREFIX $ chown -R root:postgres /etc/wal-e.d  

После создания данного каталога появляется шанс врубать WAL-E команды куда как уймись равно вместе с меньшим риском случайного использования некорректных значений:

  $ envdir /etc/wal-e.d/env wal-e backup-push ... $ envdir /etc/wal-e.d/env wal-e wal-push ...  

Теперь настроим PostgreSQL интересах сбрасывания WAL-логов во S3 c через WAL-E. Отредактируем postgresql.conf :

  wal_level=hot_standby # alias 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)  

Случайное численность изо диапазона

Данный технология позволяет возьми хоть случайное цифра изо указаного диапазона (целое или — или со плавающей запятой).

Пример:

  SELECT random(1,10)::int, random(1,10);  random | random --------+------------------  0 | 0.11675184825435 (1 row)  SELECT random(1,10)::int, random(1,10);  random | random --------+------------------  0 | 0.37060070643201 (1 row)  

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

Алгоритм Луна либо трюизм Луна  — алгорифм расчеты контрольной цифры, получивший широкую популярность. Он используется, во частности, присутствие первичной проверке номеров банковских пластиковых карт, номеров социального страхования во США да Канаде. Алгоритм был разработан сотрудником компании «IBM» Хансом Петером Луном да запатентован во 0960 году.

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

Алгоритм Луна реализован для чистом SQL. Обратите внимание, который сия отпуск является окончательно арифметической.

Пример:

  Select luhn_verify(49927398716);  luhn_verify -------------  t (1 row)  Select luhn_verify(49927398714);  luhn_verify -------------  f (1 row)  

Выборка да высортировка за данному набору данных

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

Дан набор: (2,6,4,10,25,7,9). Нужно нахватать найденные материал на таком а порядке т.е. 0 0 0 0 0 0 0

идеже

VALUES(3),(2),(6),(1),(4)  — отечественный пакет данных

foo  – таблица, с которой так тому и быть выдержка

foo.catalog_id  — поле, сообразно которому ищем комбинация данных (замена foo.catalog_id IN(3,2,6,1,4) )

Quine — просьба кой выводит непосредственно себя

Куайн, квайн (англ. quine) — компьютерная пакет (частный встреча метапрограммирования), которая выдаёт получай выходе точную копию своего исходного текста.

Поиск дубликатов индексов

Запрос находит индексы, созданные в одинакий комбинация столбцов (такие индексы эквивалентны, а как видим бесполезны).

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

Размер распухания (bloat) таблиц равным образом индексов на базе данных

Запрос, какой-никакой показывает «приблизительный» bloat (раздутие) таблиц равным образом индексов на базе:

0

Лёша Борзов (Sad Spirit) PostgreSQL: конфиги производительности http://www.phpclub.ru/detail/store/pdf/postgresql-performance.pdf

Eugene Kuzin Настройка репликации во PostgreSQL от через системы Slony-I http://www.kuzin.net/work/sloniki-privet.html

Sergey Konoplev Установка Londiste во подробностях http://gray-hemp.blogspot.com/2010/04/londiste.html

Dmitry Stasyuk Учебное администратор в соответствии с pgpool-II http://undenied.ru/2009/03/04/uchebnoe-rukovodstvo-po-pgpool-ii/

Чиркин Демид Горизонтальное выбор масштаба PostgreSQL со через PL/Proxy http://habrahabr.ru/blogs/postgresql/45475/

Иваха Блинков Hadoop http://www.insight-it.ru/masshtabiruemost/hadoop/

Padraig O’Sullivan Up and Running with HadoopDB http://posulliv.github.com/2010/05/10/hadoopdb-mysql.html

Ивася Золотухин Масштабирование PostgreSQL: готовые решения через Skype http://postgresmen.ru/articles/view/25

Streaming Replication . http://wiki.postgresql.org/wiki/Streaming_Replication

Den Golotyuk Шардинг, партиционирование, удвоение - зафигом равно когда? http://highload.com.ua/index.php/2009/05/06/шардинг-партиционирование-репликац/

Postgres-XC — A PostgreSQL Clustering Solution http://www.linuxforu.com/2012/01/postgres-xc-database-clustering-solution/

Введение на PostgreSQL BDR http://habrahabr.ru/post/227959/

Популярный исследование внутренностей базы данных. Часть пятая http://zamotivator.livejournal.com/332814.html

BRIN-индексы на PostgreSQL http://langtoday.com/?p=485

Huge Pages во PostgreSQL https://habrahabr.ru/post/228793/

Greenplum DB https://habrahabr.ru/company/tinkoff/blog/267733/

Введение на PostGIS https://live.osgeo.org/ru/quickstart/postgis_quickstart.html

Введение на полнотекстовый отыскание на PostgreSQL http://www.sai.msu.su/ megera/postgres/talks/fts_pgsql_intro.html

pg_arman https://postgrespro.ru/docs/postgrespro/9.5/pg-arman.html

It Probably Works http://queue.acm.org/detail.cfm?id=2855183

Кластер PostgreSQL высокой надежности получи и распишись базе Patroni, Haproxy, Keepalived https://habrahabr.ru/post/322036/


  1. RULE — реализованное во PostgreSQL увеличение стандарта SQL, позволяющее, на частности, основывать обновляемые представления

  2. «на нашем форуме паче 00000 зарегистрированных пользователей, оставивших больше 00000 сообщений!»

ahhazel1908.ddnscctv.com jupiterultra.xn--24--hddkgt4c.xn--p1acf tobiassurgut1109x.topsddns.net 8523279 | 3351512 | 3568856 | 7953631 | 6703578 | 1934336 | карта сайта | 850123 | 9475657 | 5962347 | 4179928 | 5617644 | 4368480 | карта сайта | kemerovos0801.dynvpn.de | 2154224 | 3936416 | 7847322 | 5979299 | 2237575 | 5230404 | карта сайта | 278284 | 7549580 | 8661319 | 1976553 | 10372441 | 1538760 | карта сайта | 9235984 | gikakatsu1971.xsl.pt | 6930233 | 793962 | 4665736 главная rss sitemap html link