在 PostgreSQL 10 for Zabbix 3.4 中自动进行本地范围分区
Automate Native Range Partitioning in PostgreSQL 10 for Zabbix 3.4
我想使用 PostgreSQL 的本机范围分区自动对 Zabbix 3.4 数据库进行分区。
编写一个 SQL 函数来执行以下操作或使用 shell/python 脚本会更明智吗?
- 确保在需要之前至少创建一个分区。
- 删除任何早于 x weeks/months 的分区;
history
7 天和 trends
1 年
以下是我从没有分区的 PSQL 9.4 填充数据库过渡到 PSQL 10 本机范围分区的解决方案。
一个。创建一个 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;
乙。在 clock
列
上创建 table 和原生范围分区
在 Zabbix DB 中创建 tables 并为时钟列实现本机范围分区。下面是一个手动 SQL 脚本的示例,history
table 可能会很有趣。对您要通过范围进行分区的所有 history
table 执行此操作。
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。自动化!
我使用了一个 shell 脚本,因为它是处理在 PSQL 中创建新分区的最简单方法之一。 10. 确保您总是至少比其他分区早一个分区需要。
让我们调用脚本auto_history_tables_monthly.sh
。
在 Debian 8 Flavor OS 上 运行s PSQL 10 确保脚本位于特定目录(我使用 /usr/local/bin
)并具有正确的权限( chown postgres:postgres /usr/local/bin/auto_history_tables_monthly.sh
) 并使其执行 table(chmod u+x /usr/local/bin/auto_history_tables_monthly.sh
作为 postgres
用户)。
使用以下内容为 postgres
用户创建一个 cron 作业 (crontab -e
):
0 0 1 * * /usr/local/bin/auto_history_tables_monthly.sh | psql -d zabbix
这将 运行 shell 脚本在每个月的第一天。
下面是脚本。它使用 date
命令来利用 UTC 纪元值。它提前一个月创建 table 并删除 2 个月前的分区。这似乎与根据我的需要定制的 history
的 31 天保留一起使用效果很好。确保 PSQL 10 DB 在此用例中处于 UTC 时间。
#!/bin/bash
month_diff () {
year=
month=
delta_month=
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=
month=
date '+%s' -d "$year-$month-01 00:00:00" -u
}
month_end () {
year=
month=
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
.
我敢肯定还有更复杂的解决方案,但我发现这对于使用 PostgreSQL 10 本机范围分区功能自动分区 Zabbix 数据库的需求来说是最简单的。
如果您需要更多详细信息,请告诉我。
我已经写了关于使用 PostgreSQL 版本 11 和 pgpartman 作为本地 table Zabbix 分区机制(撰写本文时为 3.4 版)的详细说明。
我想使用 PostgreSQL 的本机范围分区自动对 Zabbix 3.4 数据库进行分区。
编写一个 SQL 函数来执行以下操作或使用 shell/python 脚本会更明智吗?
- 确保在需要之前至少创建一个分区。
- 删除任何早于 x weeks/months 的分区;
history
7 天和trends
1 年
以下是我从没有分区的 PSQL 9.4 填充数据库过渡到 PSQL 10 本机范围分区的解决方案。
一个。创建一个 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;
乙。在 clock
列
在 Zabbix DB 中创建 tables 并为时钟列实现本机范围分区。下面是一个手动 SQL 脚本的示例,history
table 可能会很有趣。对您要通过范围进行分区的所有 history
table 执行此操作。
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。自动化!
我使用了一个 shell 脚本,因为它是处理在 PSQL 中创建新分区的最简单方法之一。 10. 确保您总是至少比其他分区早一个分区需要。
让我们调用脚本auto_history_tables_monthly.sh
。
在 Debian 8 Flavor OS 上 运行s PSQL 10 确保脚本位于特定目录(我使用 /usr/local/bin
)并具有正确的权限( chown postgres:postgres /usr/local/bin/auto_history_tables_monthly.sh
) 并使其执行 table(chmod u+x /usr/local/bin/auto_history_tables_monthly.sh
作为 postgres
用户)。
使用以下内容为 postgres
用户创建一个 cron 作业 (crontab -e
):
0 0 1 * * /usr/local/bin/auto_history_tables_monthly.sh | psql -d zabbix
这将 运行 shell 脚本在每个月的第一天。
下面是脚本。它使用 date
命令来利用 UTC 纪元值。它提前一个月创建 table 并删除 2 个月前的分区。这似乎与根据我的需要定制的 history
的 31 天保留一起使用效果很好。确保 PSQL 10 DB 在此用例中处于 UTC 时间。
#!/bin/bash
month_diff () {
year=
month=
delta_month=
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=
month=
date '+%s' -d "$year-$month-01 00:00:00" -u
}
month_end () {
year=
month=
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
.
我敢肯定还有更复杂的解决方案,但我发现这对于使用 PostgreSQL 10 本机范围分区功能自动分区 Zabbix 数据库的需求来说是最简单的。
如果您需要更多详细信息,请告诉我。
我已经写了关于使用 PostgreSQL 版本 11 和 pgpartman 作为本地 table Zabbix 分区机制(撰写本文时为 3.4 版)的详细说明。