0

OrioleDB : la promesse d’un No-Vacuum

twitterlinkedinmail

La gestion efficace de l’espace disque dans PostgreSQL est une préoccupation constante pour les administrateurs de bases de données. C’est là qu’intervient le processus de “vacuum”, une fonctionnalité puissante et complexe qui peut jouer un rôle déterminant dans la performance et la stabilité de votre base de données PostgreSQL. Cependant, comme toute arme à double tranchant, le vacuum apporte à la fois des avantages considérables et des défis potentiels.

Le principal reproche que l’on peut adresser au système de vacuum (et à l’auto-vacuum par extension) est sa consommation importante de ressources. C’est l’une des raisons majeures évoquées par les grandes entreprises qui optent pour un autre SGBD, comme Uber, qui a migré vers MySQL pour remplacer PostgreSQL.

OrioleDB nous propose une approche novatrice de la gestion de la fragmentation (bloat) et de l’espace disque de vos tables PostgreSQL. La principale promesse de ce nouveau moteur développé par la société Oriole est d’éliminer le besoin de vacuum régulier et de longues périodes de maintenance pour nos bases de données.

Cette innovation s’articule autour de journaux d’annulation au niveau de la ligne et du bloc, ainsi que de la fusion automatique des pages. Les journaux d’annulation au niveau des lignes et des blocs offrent un contrôle plus précis, permettant une gestion plus efficace des modifications de données. La fonction de fusion automatique des pages travaille en arrière-plan pour regrouper les données fragmentées, améliorant ainsi encore davantage l’efficacité du système. Le moteur est actuellement disponible en version bêta sur le site d’OrioleDB.

Dans cet article, je vais vous montrer comment installer OrioleDB et réaliser un test comparatif entre une instance classique et une instance OrioleDB en termes d’espace disque occupé. Je vais utiliser notre agent AllDB de supervision des bases de données pour générer des graphiques de la consommation d’espace disque.

Installation d’OrioleDB :

Pour pouvoir tester le nouveau moteur, il nous faut l’installer. Pour cela, deux solutions s’offrent à nous. On peut choisir de le compiler nous-mêmes à partir du code source fourni par Oriole, ou on peut choisir d’utiliser le conteneur Docker mis à notre disposition.

Pour des raisons de rapidité de mise en place, j’ai choisi d’utiliser le conteneur fourni.

Pour commencer, j’installe Docker sur ma machine.

root@ip-172-44-2-190:~$ sudo apt-get update
(...)
Reading package lists... Done
root@ip-172-44-2-190:~$ sudo apt-get install ca-certificates curl gnupg
Reading package lists... Done
(...)
No VM guests are running outdated hypervisor (qemu) binaries on this host.
root@ip-172-44-2-190:~$ sudo install -m 0755 -d /etc/apt/keyrings
root@ip-172-44-2-190:~$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
root@ip-172-44-2-190:~$ sudo chmod a+r /etc/apt/keyrings/docker.gpg
root@ip-172-44-2-190:~$ echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
Hit:1 http://eu-west-3.ec2.archive.ubuntu.com/ubuntu jammy InRelease
Hit:2 http://eu-west-3.ec2.archive.ubuntu.com/ubuntu jammy-updates InRelease
(...)
No VM guests are running outdated hypervisor (qemu) binaries on this host.

Pour tester que mon installation fonctionne correctement, je peux démarrer l’image hello-world par défaut de Docker.

root@ip-172-44-2-190:~$ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
719385e32844: Pull complete
Digest: sha256:4f53e2564790c8e7856ec08e384732aa38dc43c52f02952483e3f003afbf23db
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/

For more examples and ideas, visit:
https://docs.docker.com/get-started/

Docker est correctement installé, nous pouvons à présent aller récupérer l’image Oriole depuis les dépôts (repositories). J’ai choisi de récupérer l’image “latest” de la version 14, avec laquelle je vais effectuer mes tests.

root@ip-172-44-2-190:~# docker pull orioledb/orioledb:latest-pg14
latest-pg14: Pulling from orioledb/orioledb
7264a8db6415: Pull complete
4e0888d8a332: Pull complete
4b0510894ae7: Pull complete
dc5da57566a1: Pull complete
9611602787a1: Pull complete
8f68f9452236: Pull complete
5c92ed25d025: Pull complete
11bb162cfe7a: Pull complete
6f375d990892: Pull complete
6ac166496e68: Pull complete
Digest: sha256:4d408916e929ff0bcea11fee91ca5e69b0929be1afa58b5dbbcddcce340089ef
Status: Downloaded newer image for orioledb/orioledb:latest-pg14
docker.io/orioledb/orioledb:latest-pg14

On vérifie que notre image est bien présente, et on l’éxecute :

root@ip-172-44-2-190:~# docker image ls --all
REPOSITORY TAG IMAGE ID CREATED SIZE
orioledb/orioledb latest-pg14 cd7f629f705e 10 days ago 270MB
hello-world latest 9c7a54a9a43c 4 months ago 13.3kB 
root@ip-172-44-2-190:~# docker run -e POSTGRES_PASSWORD=password cd7f629f705e
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.utf8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english".

Data page checksums are disabled.

fixing permissions on existing directory /var/lib/postgresql/data ... ok
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... UTC
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... sh: locale: not found
2023-09-21 09:51:08.177 UTC [30] WARNING: no usable system locales were found
ok
syncing data to disk ... ok

Success. You can now start the database server using:

pg_ctl -D /var/lib/postgresql/data -l logfile start

initdb: warning: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.
waiting for server to start....2023-09-21 09:51:09.294 UTC [36] LOG: OrioleDB public beta 2 started
2023-09-21 09:51:09.295 UTC [36] LOG: starting PostgreSQL 14.9 OrioleDB public beta 2 PGTAG=patches14_16 alpine:3.18+clang-15 build:2023-09-10T16:41:50+00:00 on x86_64-pc-linux-musl, compiled by Alpine clang version 15.0.7, 64-bit
2023-09-21 09:51:09.300 UTC [36] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-09-21 09:51:09.316 UTC [37] LOG: database system was shut down at 2023-09-21 09:51:08 UTC
2023-09-21 09:51:09.316 UTC [38] LOG: orioledb background writer started
2023-09-21 09:51:09.323 UTC [36] LOG: database system is ready to accept connections
done
server started

/usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*

waiting for server to shut down...2023-09-21 09:51:09.350 UTC [36] LOG: received fast shutdown request
.2023-09-21 09:51:09.353 UTC [36] LOG: aborting any active transactions
2023-09-21 09:51:09.354 UTC [38] LOG: orioledb bgwriter is shut down
2023-09-21 09:51:09.357 UTC [36] LOG: background worker "logical replication launcher" (PID 44) exited with exit code 1
2023-09-21 09:51:09.357 UTC [39] LOG: shutting down
2023-09-21 09:51:09.360 UTC [39] LOG: orioledb checkpoint 1 started
2023-09-21 09:51:09.601 UTC [39] LOG: orioledb checkpoint 1 complete
2023-09-21 09:51:09.631 UTC [36] LOG: database system is shut down
done
server stopped

PostgreSQL init process complete; ready for start up.

2023-09-21 09:51:09.712 UTC [1] LOG: OrioleDB public beta 2 started
2023-09-21 09:51:09.764 UTC [1] LOG: starting PostgreSQL 14.9 OrioleDB public beta 2 PGTAG=patches14_16 alpine:3.18+clang-15 build:2023-09-10T16:41:50+00:00 on x86_64-pc-linux-musl, compiled by Alpine clang version 15.0.7, 64-bit
2023-09-21 09:51:09.764 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2023-09-21 09:51:09.764 UTC [1] LOG: listening on IPv6 address "::", port 5432
2023-09-21 09:51:09.770 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2023-09-21 09:51:09.778 UTC [49] LOG: database system was shut down at 2023-09-21 09:51:09 UTC
2023-09-21 09:51:09.778 UTC [50] LOG: orioledb background writer started
2023-09-21 09:51:09.785 UTC [1] LOG: database system is ready to accept connections
2023-09-21 09:54:23.633 UTC [68] FATAL: role "root" does not exist
2023-09-21 09:56:09.884 UTC [51] LOG: orioledb checkpoint 2 started
2023-09-21 09:56:10.100 UTC [51] LOG: orioledb checkpoint 2 complete 

Notre serveur est correctement démarré. Nous pouvons maintenant nous y connecter à partir d’un autre terminal et préparer le cas de test. Pour ce faire, nous allons créer une nouvelle base de données sur laquelle nous effectuerons un test de charge avec pg_bench.

root@ip-172-44-2-190:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
11c0860b7abc cd7f629f705e "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 5432/tcp funny_hellman
root@ip-172-44-2-190:~# docker exec -it 11c0860b7abc bash
11c0860b7abc:/# su - postgres
11c0860b7abc:~$ psql
psql (14.9 OrioleDB public beta 2 PGTAG=patches14_16 alpine:3.18+clang-15 build:2023-09-10T16:41:50+00:00)
Type "help" for help.
postgres=# create database pg_bench;
CREATE DATABASE
postgres=# \c pg_bench
You are now connected to database "pg_bench" as user "postgres".
pg_bench=# CREATE TABLE test (
pg_bench(# id integer primary key,
pg_bench(# value1 float8 not null,
pg_bench(# value2 float8 not null,
pg_bench(# value3 float8 not null,
pg_bench(# value4 float8 not null,
pg_bench(# ts timestamp not null
pg_bench(# );
CREATE TABLE
pg_bench=# CREATE INDEX test_value1_idx ON test (value1);
CREATE INDEX
pg_bench=# CREATE INDEX test_value2_idx ON test (value2);
CREATE INDEX
pg_bench=# CREATE INDEX test_value3_idx ON test (value3);
CREATE INDEX
pg_bench=# CREATE INDEX test_value4_idx ON test (value4);
CREATE INDEX
pg_bench=# CREATE INDEX test_ts_idx ON test (ts);
CREATE INDEX 

Notre environnement de test est prêt. Afin de pouvoir comparer les performances avec une instance PostgreSQL plus traditionnelle, j’ai également installé une version legacy en local sur la machine que j’utilise. J’ai créé la même table et les mêmes index que dans mon conteneur Docker. Pour réaliser ce test, j’ai repris le script pg_bench de test fourni par Oriole.

11c0860b7abc:~$ cat test.sql
\set id random(1, 10000000)
INSERT INTO test VALUES(:id, random(), random(), random(), random(), now() - random() * random() * 1800 * interval '1 second')
ON CONFLICT (id) DO UPDATE SET ts = now();

Ce petit script de test permet de lancer des insertions successives de données dans notre table de test. Il est conçu pour maximiser les chances de fragmentation à mesure que nous insérons des données dans notre table, car les doublons de clé primaire entraînent la mise à jour d’anciennes lignes. Cela devrait donc nous permettre de constater la différence d’espace disque entre une version standard de PostgreSQL et la version du moteur développée par Oriole.

Résultats des test :

Mes tests sont réalisés sur une machine Amazon EC2 de type “large”, équipée de 7 gigaoctets de RAM et de 2 unités de traitement central (CPU).

Voici la capture d’écran de l’occupation de l’espace disque pour le premier test, celui concernant l’instance OrioleDB :

On peut observer que la progression de la taille de l’instance est régulière et très modérée. Pendant le test, j’ai surveillé l’utilisation de la RAM de la machine, qui atteignait un pic à 95 % et demeurait relativement stable pendant toute la durée du test. Conformément à la promesse du moteur, aucun processus d’autovacuum n’a été constaté pendant le processus.

En comparaison, le graphique de la base de données non Oriole présente une nette différence :

On observe notamment de nombreux pics et chutes fréquents dus aux vacuums organisés régulièrement. Le tracé n’est pas linéaire.

De plus, en surveillant les valeurs d’utilisation CPU, à la différence d’Oriole où les valeurs étaient constantes car il était toujours en train d’ajouter des données, les moments de vacuum de la base provoquent d’importantes montées de charge, suivies de chutes lorsque ces processus sont terminés sur notre instance de base.

Conclusion :

Sur le blog d’OrioleDB, les graphiques affichés sont le résultat de l’injection de 80 gigaoctets de données dans leur base de données à l’aide de pg_bench. Cependant, lorsque l’on examine les spécifications de la machine qu’ils ont utilisée pour leurs tests, on se rend compte qu’elle n’est pas à la portée de toutes les bourses. La machine utilisée comprend en effet 72 CPU et dispose d’un total de 144 Go de RAM, une configuration que très peu de personnes, principalement en raison du coût élevé de ce type de matériel, pourraient envisager pour leur infrastructure.

Oriole fonctionne, comme nous l’avons vu sur les graphiques que j’ai commentés précédemment. Cependant, il s’agit d’un outil conçu pour les architectures de très grande envergure et les besoins importants en termes d’entrées/sorties de données. Les gains ne sont pas aussi significatifs sur des machines de plus petite taille, qui correspondent davantage à la réalité de nombreuses entreprises actuelles.

Continuez votre lecture sur le blog :

twitterlinkedinmail

Sarah FAVEERE

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.