Among the different possibilities for Zabbix storage, one piqued my curiosity: TimescaleDB
TimescaleDB is a time series database plugin for PostgreSQL. Joël Cattin already blogged about it here from a general point of view. In this blog post, I will focus on Zabbix setup and visible improvements.
Overview
As a reminder, my Zabbix was installed with a PostgreSQL database backend, thus migration to TimescaleDB should be easy. I will follow these steps:
- Install TimescaleDB
- Enable TimescaleDB extension in PostgreSQL
- Migrate tables to hypertables
TimescaleDB Installation
Before starting anything, we must stop Zabbix services:
systemctl stop zabbix-java-gateway.service
systemctl stop zabbix-agent.service
systemctl stop zabbix-server.service
Next, we can add TimescaleDB repository:
tee /etc/yum.repos.d/timescale_timescaledb.repo <<EOL
[timescale_timescaledb]
name=timescale_timescaledb
baseurl=https://packagecloud.io/timescale/timescaledb/el/$(rpm -E %{rhel})/\$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/timescale/timescaledb/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
EOL
Run a simple yum update and install package:
yum install timescaledb-2-postgresql-15
Enable TimescaleDB Extension
Next step is to make PostgreSQL preload the newly installed library by add timescaledb to the shared_preload_libraries parameter in /u02/pgdata/15/zabbix/postgresql.conf configuration file:
shared_preload_libraries = 'timescaledb'
On a standard Zabbix setup, there will be no existing line with shared_preload_libraries. If you have already a line like that, you must add timescaledb to the parameter and not replacing it completely.
Then, we need to restart the database:
systemctl restart postgres-zabbix.service
And we don’t forget to check it is running after that:
$ systemctl status postgres-zabbix.service
● postgres-zabbix.service - PostgreSQL for Zabbix
   Loaded: loaded (/etc/systemd/system/postgres-zabbix.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2023-09-04 15:08:58 CEST; 1s ago
 Main PID: 12370 (postgres)
    Tasks: 8 (limit: 23220)
   Memory: 21.6M
And one last check to confirm extension is present1:
# select extname, extversion from pg_extension;
   extname   | extversion
-------------+------------
 plpgsql     | 1.0
 timescaledb | 2.11.2
(2 rows)
Subsequently, we must enable extension for zabbix database2.
echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix
Expected output is the following:
WARNING:
WELCOME TO
 _____ _                               _     ____________
|_   _(_)                             | |    |  _  \ ___ \
  | |  _ _ __ ___   ___  ___  ___ __ _| | ___| | | | |_/ /
  | | | |  _ ` _ \ / _ \/ __|/ __/ _` | |/ _ \ | | | ___ \
  | | | | | | | | |  __/\__ \ (_| (_| | |  __/ |/ /| |_/ /
  |_| |_|_| |_| |_|\___||___/\___\__,_|_|\___|___/ \____/
               Running version 2.11.2
For more information on TimescaleDB, please visit the following links:
 1. Getting started: https://docs.timescale.com/timescaledb/latest/getting-started
 2. API reference documentation: https://docs.timescale.com/api/latest
 3. How TimescaleDB is designed: https://docs.timescale.com/timescaledb/latest/overview/core-concepts
Note: TimescaleDB collects anonymous reports to better understand and assist our users.
For more information and how to disable, please see our docs https://docs.timescale.com/timescaledb/latest/how-to-guides/configuration/telemetry.
CREATE EXTENSION
If extension is not preloaded, a message like that will show:
FATAL:  extension "timescaledb" must be preloaded
HINT:  Please preload the timescaledb library via shared_preload_libraries.
Migrate Tables
Finally, we can run the sql script provided with Zabbix to migrate tables to hypertables.
$ cat /usr/share/zabbix-sql-scripts/postgresql/timescaledb.sql | sudo -u zabbix psql zabbix
NOTICE:  PostgreSQL version 15.4 is valid
NOTICE:  TimescaleDB extension is detected
NOTICE:  TimescaleDB version 2.11.2 is valid
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
WARNING:  column type "character varying" used for "source" does not follow best practices
HINT:  Use datatype TEXT instead.
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
WARNING:  column type "character varying" used for "value" does not follow best practices
HINT:  Use datatype TEXT instead.
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
NOTICE:  migrating data to chunks
DETAIL:  Migration might take a while depending on the amount of data.
NOTICE:  TimescaleDB is configured successfully
DO
Database is migrated; thus we can start Zabbix services:
systemctl start zabbix-java-gateway.service
systemctl start zabbix-agent.service
systemctl start zabbix-server.service
Verifications
My first check is to list the created hypertables:
# select hypertable_name from timescaledb_information.hypertables where owner = 'zabbix';
 hypertable_name
-----------------
 history
 history_uint
 history_str
 history_text
 history_log
 trends
 trends_uint
(7 rows)
I can also list the list of jobs managed by TimescaleDB3:
# select job_id, application_name, hypertable_name FROM timescaledb_information.jobs;
 job_id |        application_name        | hypertable_name
--------+--------------------------------+-----------------
      2 | Error Log Retention Policy [2] |
      1 | Telemetry Reporter [1]         |
   1000 | Compression Policy [1000]      | history
   1001 | Compression Policy [1001]      | history_uint
   1002 | Compression Policy [1002]      | history_str
   1003 | Compression Policy [1003]      | history_text
   1004 | Compression Policy [1004]      | history_log
   1005 | Compression Policy [1005]      | trends
   1006 | Compression Policy [1006]      | trends_uint
(9 rows)
My Zabbix server does not ingest so many values (ie. trends, events, tags), thus the advantage on storage might not be so good as on a more loaded server. Nevertheless, I can see some benefits:
# SELECT pg_size_pretty(before_compression_total_bytes) as "before compression", pg_size_pretty(after_compression_total_bytes) as "after compression" FROM hypertable_compression_stats('trends');
 before compression | after compression
--------------------+-------------------
 1272 kB            | 672 kB
(1 row)
# SELECT pg_size_pretty(before_compression_total_bytes) as "before compression", pg_size_pretty(after_compression_total_bytes) as "after compression" FROM hypertable_compression_stats('history_uint');
 before compression | after compression
--------------------+-------------------
 872 kB             | 528 kB
(1 row)
I will add more agent to my Zabbix setup and follow these compression figures closely.
![Thumbnail [90x90]](https://www.dbi-services.com/blog/wp-content/uploads/2022/09/DDI_web-min-scaled.jpg) 
							
							![Thumbnail [90x90]](https://www.dbi-services.com/blog/wp-content/uploads/2022/08/MOP_web-min-scaled.jpg) 
							
							
Ano
14.12.2023Thanks for this useful and very clear aritcle. I'tried this and worked everything fine so far, til the part with the jobs. I don't see jobs. Do you migth know, what I did wrong here?
Thx and regards Ano
Hi Ano,
thanks for your comment.
I did retry the procedure and was also missing Compression Policies. After a quick look in zabbix sources, I noticed that these are created by the housekeeper which is triggered every hour.
Did you recheck after 1 hour?
I hope you are at least seeing the two first jobs (job_id 1 and 2).
Regards,
Olivier