Автоматизируйте разделение собственного диапазона в PostgreSQL 10 для Zabbix 3.4 - PullRequest
0 голосов
/ 16 мая 2018

Я хотел бы автоматизировать процесс разбиения базы данных Zabbix 3.4 с помощью PostgreSQL Native Range Partitioning.

Было бы разумнее написать функцию SQL для выполнения следующего ниже или использовать скрипт shell / python?

  • Убедитесь, что хотя бы один раздел создан раньше, чем нужно.
  • Удалите любой раздел старше x недель / месяцев;на history 7 дней и на trends 1 год

Ответы [ 2 ]

0 голосов
/ 09 апреля 2019

Я написал подробные заметки об использовании PostgreSQL версии 11 вместе с pgpartman в качестве механизма для разбиения собственных таблиц с помощью Zabbix (версия 3.4 на момент написания этой статьи).

Zabbix-Postgres-разбиение

0 голосов
/ 31 мая 2018

Ниже приведено решение, которое я придумала для перехода к разделу с собственным диапазоном PSQL 10 из заполненной базы данных PSQL 9.4 без разделения.

A. Создайте пустую базу данных Zabbix для PSQL 10.

Убедитесь, что сначала создайте пустую Zabbix PSQL 10 DB.

# su postgres
postgres@<>:~$ createuser -P -s -e zabbix
postgres@<>:~$ psql
postgres# create database zabbix;
postgres# grant all privileges on database zabbix to zabbix;

B. Создание таблиц и разделов собственного диапазона в столбце clock

Создайте таблицы в базе данных Zabbix и внедрите разделение собственного диапазона для столбца часов. Ниже приведен пример ручного сценария SQL, который может быть интересен для history таблицы. Выполните это для всех history таблиц, которые вы хотите разделить по диапазону.

zabbix=# CREATE TABLE public.history
(
    itemid bigint NOT NULL,
    clock integer NOT NULL DEFAULT 0,
    value numeric(20,0) NOT NULL DEFAULT (0)::numeric,
    ns integer NOT NULL DEFAULT 0
) PARTITION BY RANGE (clock);

zabbix=# CREATE TABLE public.history_old PARTITION OF public.history
    FOR VALUES FROM (MINVALUE) TO (1522540800);
zabbix=# CREATE TABLE public.history_y2018m04 PARTITION OF public.history
    FOR VALUES FROM (1522540800) TO (1525132800);
zabbix=# CREATE TABLE public.history_y2018m05 PARTITION OF public.history
    FOR VALUES FROM (1525132800) TO (1527811200);

zabbix=# CREATE INDEX ON public.history_old USING btree (itemid, clock);
zabbix=# CREATE INDEX ON public.history_y2018m04 USING btree (itemid, clock);
zabbix=# CREATE INDEX ON public.history_y2018m05 USING btree (itemid, clock);

C. Автоматизируй это!

Я использовал сценарий оболочки, потому что это один из самых простых способов создания новых разделов в PSQL 10. Убедитесь, что вы всегда по крайней мере на один раздел впереди того, что нужно.

Давайте назовем скрипт auto_history_tables_monthly.sh.

В операционной системе Debian 8 Flavor, которая запускает PSQL 10, убедитесь, что скрипт находится в определенном каталоге (я использовал /usr/local/bin) с правильными разрешениями (chown postgres:postgres /usr/local/bin/auto_history_tables_monthly.sh), и сделайте его исполняемым (chmod u+x /usr/local/bin/auto_history_tables_monthly.sh как пользователь postgres) .

Создать задание cron (crontab -e) для пользователя postgres со следующими параметрами:

0 0 1 * * /usr/local/bin/auto_history_tables_monthly.sh | psql -d zabbix

Это будет запускать скрипт оболочки первое число каждого месяца.

Ниже приведен сценарий. Он использует команду date для использования значения эпохи UTC. Он создает таблицу за месяц и отбрасывает раздел на 2 месяца старше. Похоже, это хорошо работает в сочетании с 31-дневным сроком хранения history, настроенным в соответствии с моими потребностями. Убедитесь, что для этого варианта использования БД PSQL 10 работает по UTC.

#!/bin/bash

month_diff () {
        year=$1
  month=$2
        delta_month=$3
  x=$((12*$year+10#$month-1))
        x=$((x+$delta_month))
        ry=$((x/12))
        rm=$(((x % 12)+1))
        printf "%02d %02d\n" $ry $rm
}

month_start () {
        year=$1
  month=$2
        date '+%s' -d "$year-$month-01 00:00:00" -u
}

month_end () {
        year=$1
  month=$2
        month_start $(month_diff $year $month 1)
}

# Year using date
current_year=$(date +%Y)
current_month=$(date +%m)

# Math
next_date=$(month_diff $current_year $current_month 1)
next_year=$(echo $next_date|sed 's/ .*//')
next_month=$(echo $next_date|sed 's/.* //')

start=$(month_start $next_date)
end=$(month_end $next_date)

#next_month_table="public.history_y${next_year}m${next_month}"

# Create next month table for history, history_uint, history_str, history_log, history_text
sql="
    CREATE TABLE IF NOT EXISTS public.history_y${next_year}m${next_month} PARTITION OF public.history
      FOR VALUES FROM ($start) TO ($end);
    \nCREATE TABLE IF NOT EXISTS public.history_uint_y${next_year}m${next_month} PARTITION OF public.history_uint
      FOR VALUES FROM ($start) TO ($end);
    \nCREATE TABLE IF NOT EXISTS public.history_str_y${next_year}m${next_month} PARTITION OF public.history_str
      FOR VALUES FROM ($start) TO ($end);
    \nCREATE TABLE IF NOT EXISTS public.history_log_y${next_year}m${next_month} PARTITION OF public.history_log
      FOR VALUES FROM ($start) TO ($end);
    \nCREATE TABLE IF NOT EXISTS public.history_text_y${next_year}m${next_month} PARTITION OF public.history_text
      FOR VALUES FROM ($start) TO ($end);
    \nCREATE INDEX on public.history_y${next_year}m${next_month} USING btree (itemid, clock);
    \nCREATE INDEX on public.history_uint_y${next_year}m${next_month} USING btree (itemid, clock);
    \nCREATE INDEX on public.history_str_y${next_year}m${next_month} USING btree (itemid, clock);
    \nCREATE INDEX on public.history_log_y${next_year}m${next_month} USING btree (itemid, clock);
    \nCREATE INDEX on public.history_text_y${next_year}m${next_month} USING btree (itemid, clock);
    "

echo -e $sql

# Math
prev_date=$(month_diff $current_year $current_month -2)
prev_year=$(echo $prev_date|sed 's/ .*//')
prev_month=$(echo $prev_date|sed 's/.* //')

# Drop last month table for history, history_uint, history_str, history_log, history_text
sql="
    DROP TABLE public.history_y${prev_year}m${prev_month};
    \nDROP TABLE public.history_uint_y${prev_year}m${prev_month};
    \nDROP TABLE public.history_str_y${prev_year}m${prev_month};
    \nDROP TABLE public.history_log_y${prev_year}m${prev_month};
    \nDROP TABLE public.history_text_y${prev_year}m${prev_month};
    "

echo -e $sql

D. Затем сбросьте данные из старой базы данных внутри. Я использовал pg_dump/pg_restore.

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

Пожалуйста, дайте мне знать, если вам нужно больше деталей.

...