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