18
0
Fork 0
wiki/HowtoPostgreSQL.md

25 KiB

title: Howto PostgreSQL : installation et utilisation courante categories: databases ... * Documentation : http://www.postgresql.org/docs/current/static/ * Wiki : https://wiki.postgresql.org/wiki/Main_Page * Rôle Ansible : https://forge.evolix.org/projects/ansible-roles/repository/show/postgresql PostgreSQL est une base de données qui met l'accent sur le respect du standard SQL. ## Installation ~~~ # apt install postgresql # /usr/lib/postgresql/9.4/bin/postgres -V postgres (PostgreSQL) 9.4.9 ~~~ Suite à l'installation, une première instance main est créée avec les paramètres par défaut. ### Dépôt PGDG Le PostgreSQL Global Development Group (PGDG) maintient un dépôt Debian qui contient plusieurs versions majeures de PostgreSQL (plus récentes et plus anciennes) que celle disponible dans Debian stable, ainsi que plusieurs extensions au serveur. Ajouter le dépôt un fichier sources.list /etc/apt/sources.list.d/jessie-pgdg.list : ~~~ deb http://apt.postgresql.org/pub/repos/apt/ jessie-pgdg main ~~~ Puis définir les priorités pour DPkg dans /etc/apt/preferences.d/postgresql : ~~~ Package: postgresql-9.5 postgresql-client-common postgresql-common libpq5 Pin: release a=jessie-pgdg Pin-Priority: 999 ~~~ Enfin, récupérer la clé publique GPG : ~~~ # wget --quiet -O - http://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc |apt-key add - ~~~ ### Multiples versions et instances (clusters) Une surcouche Debian permet de gérer très simplement plusieurs versions et plusieurs instances d'une même version de PostgreSQL. Cela permet entre autre de faciliter les migrations d'un version majeure à une autre. Par défaut le script d'init contrôle tous les instances actives. Pour contrôler seulement une instances en particulier : ~~~ # pg_ctlcluster start|stop|restart|reload|status|promote ~~~ Pour lister les instances existantes : ~~~ # pg_lsclusters Ver Cluster Port Status Owner Data directory Log file 9.4 main 5432 online postgres /var/lib/postgresql/9.4/main /var/log/postgresql/postgresql-9.4-main.log ~~~ Pour créer une nouvelle instance : ~~~ $ /usr/bin/pg_createcluster ~~~ Le port d'écoute de postgres sera automatiquement incrémenté de 1 pour ne pas rentrer en conflit avec les autres instances. L'encodage utilisé par défaut pour l'instance est celui du système. Si le système est en en_US.UTF-8 par défaut, l'instance créée sera en en_US.UTF-8. On peut remarquer que toute l'arborescence est organisée en fonction des versions et des instances. Cela permet de les rendre réellement indépendantes : * configuration : /etc/postgresql/<version>/<instance>/ * journaux : /var/log/postgresql/postgresql-<version>-<instance>.log * stockage : /var/lib/postgresql/<version>/<instance>/ * binaires et bibliothèques : /usr/lib/postgresql/<version>/<instance>/ * etc… ## Gestion des utilisateurs et permissions PostgreSQL permet de lier un utilisateur Unix à un utilisateur PostgreSQL. C'est le cas pour l'utilisateur postgres (superadmin PostgreSQL), qui est lié à l'utilisateur Unix postgres. Ainsi pour passer superadmin PostgreSQL : ~~~ # sudo -u postgres psql psql (9.6.0, server 9.4.9) Type "help" for help. postgres=# ~~~ À noter que l'utilisateur Unix postgres a tous les droits sur les fichiers de configuration, les journaux, etc… sur le système. Par défaut, un utilisateur Unix foo sera automatiquement lié à son compte PostgreSQL foo si il existe. C'est très pratique dans le cas de multiples comptes web sur la machine, on évite ainsi de stocker un mot de passe dans un fichier de paramètre de connexion. La gestion des permissions se fait dans le fichier de configuration pg_hba.conf de l'instance en question. Si on préfère passer par un mot de passe pour s'authentifier, il faut changer la ligne suivante dans le fichier pg_hba.conf : ~~~{.diff} - local all all peer + local all all password ~~~ Bien s'assurer que les utilisateurs PostgreSQL ont un mot de passe de définit avant ! ## Configuration La plupart des changements de configuration peuvent être pris en compte à chaud avec un reload. On verra dans ce cas les changements dans les logs : ~~~ 2016-12-20 17:02:58 CET [13555]: [2-1] user=,db= LOG: received SIGHUP, reloading configuration files 2016-12-20 17:02:58 CET [13555]: [3-1] user=,db= LOG: parameter "log_temp_files" changed to "6MB" ~~~ TODO ## Administration Toutes les commandes d'administration doivent être exécutées depuis l'utilisateur Unix postgres. * Création d'un utilisateur avec un mot de passe : ~~~ $ createuser -P ~~~ * Création d'une base de donnée, en définissant l'utilisateur précédemment créé comme propriétaire de la base : ~~~ $ createdb -O ~~~ Comme pour les instances, par défaut la base sera créé avec l'encodage du système. Si le système est en UTF-8 par défaut, la base créée sera en UTF-8. On peut spécifier un encodage alternatif avec l'option -E. * Suppression d'une base de données : ~~~ $ dropdb ~~~ * Mise à jour du mot de passe d'un utilisateur : ~~~ $ psql -c "ALTER USER WITH PASSWORD 'foo'" ~~~ * Suppression d'un utilisateur : ~~~ $ dropuser ~~~ * Lister les bases de données : ~~~ $ psql -l ~~~ ou : ~~~ =# \d ~~~ ou encore : ~~~ =# SELECT * FROM pg_database; ~~~ * Lister les utilisateurs (aussi appelés rôles) : ~~~ =# SELECT * FROM pg_user; ~~~ ou : ~~~ =# \du ~~~ * Lister les indexes : ~~~ =# \di ~~~ * Lister les triggers : ~~~ =# SELECT * FROM pg_trigger; ~~~ * Lister les triggers avec la définition SQL, la procédure exécutée, le langage et le code de la procédure : ~~~{.sql} =# SELECT t.tgname AS nom_du_trigger, pg_get_triggerdef( t.oid ) AS definition_du_trigger, p.proname AS procedure_executee, l.lanname AS langage_procedure, p.prosrc AS code_de_la_procedure FROM pg_trigger t JOIN pg_proc p ON p.oid = t.tgfoid JOIN pg_language l ON l.oid = p.prolang; ~~~ * Faire en sorte qu'un utilisateur hérite des droits d'un autre utilisateur (à vérifier) : ~~~ =# GRANT admin TO jdoe; ~~~ (Il faut que jdoe est été créé avec l'option INHERIT (c'est le cas par défaut)) * Donner les droits à un utilisateur existant de créer des bases de données (à vérifier) : ~~~ =# ALTER USER jdoe CREATEDB; ~~~ * Obtenir la taille d'une base ou des tables : ~~~ =# SELECT pg_size_pretty(pg_database_size('DB')); =# SELECT pg_size_pretty(pg_relation_size('TABLE')); =# SELECT pg_size_pretty(pg_total_relation_size('TABLE')); // taille avec les indexes =# SELECT relname, relpages FROM pg_class ORDER BY relpages DESC ~~~ Attention, pg_class semble ne pas se mettre à jour dynamiquement. Il faut apparemment faire un VACUUM ANALYZE pour forcer la mise à jour. ### Sauvegardes et restaurations des données de PostgreSQL Deux principales possibilités existent pour sauvegarder les bases de données PostgreSQL : * sauvegarde SQL : simple à mettre en place, mais lent, impacte les requêtes en cours (locks) et consomme beaucoup de place ; * sauvegarde du datadir : complètement transparent pour les connexions actives, synchro uniquement des fichiers modifiés par rapport à la dernière sauvegarde, mais plus complexe à mettre en place (gestion des WAL). #### Sauvegarde SQL Sauvegarde d'une seule base : ~~~ $ pg_dump >dump.sql ~~~ Attention : ne sauvegarde ni les tablespaces, ni les roles. Pour sauvegarder ces derniers : ~~~ $ pg_dumpall -g >dump.sql ~~~ Sauvegarde de toutes les bases : ~~~ $ pg_dumpall >dump.sql ~~~ Sauvegarde d'une table d'une base de données : ~~~ $ pg_dump -t ~~~ À moins de vouloir restaurer le contenu sur un autre moteur de base de données, il est préférable de faire des dumps au format custom, qui permet la compression, un processus de restauration sur plusieurs threads, et de sélectionner finement quels éléments restaurer lors de la restauration : ~~~ $ pg_dumpall -F c >all.dump ~~~ #### Restauration SQL Restauration de données au format SQL : ~~~ $ psql < dump.sql ~~~ Restauration de données au format custom : ~~~ $ pg_restore -F c all.dump ~~~ Important : il est nécessaire de faire un ANALYSE après une restauration de tables ou bases de données afin de mettre à jour les statistiques de PostgreSQL. Ces statistiques sont utilisées par PostgreSQL pour déterminer la manière la plus optimum de requêter la base en fonction de la répartition des valeurs des champs. Optimisations pour la restauration : * paralléliser la restauration : pg_restore -j <nb de cœurs CPU> (ne pas compter les cœurs hyperthreadés) ; * augmenter autant que possible le _maintenance_work_mem_ (attention, il sera multiplié par le nombre de processus utilisés pour la restauration). Dans tous les cas, ne pas dépasser les 2 Go. Peut être fait dans la conf ou dans une session ; * Mettre la directive synchronous_commit à off. #### Sauvegarde du datadir Doc de référence : http://www.postgresql.org/docs/9.4/static/continuous-archiving.html Le principe est le suivant : * indiquer à PostgreSQL qu'on commence une sauvegarde. Il va notamment faire un checkpoint dans son WAL courant ; * faire un rsync du datadir, en excluant les WAL (pg_xlog/*) ; * indiquer à PostgreSQL la fin de la sauvegarde, afin qu'il termine son WAL courant (pour qu'il puisse être copié par archive_command). Il faut en parallèle activer l'archivage des WAL dans la configuration : ~~~ wal_level = 'archive' # ou plus (hot_standby) archive_command = 'rsync %p backup.example.net:/backup/…/archives/%f' ~~~ Ainsi, dès qu'un WAL est marqué comme complété (pg_xlog/archive_status/*.ready), il est copié sur le serveur de backup conformément à archive_command. Si la copie à réussi, le .ready est renommé en .done. ~~~ postgres$ psql -c "SELECT pg_start_backup('evobackup')" # rsync -a --delete --exclude /pg_xlog/* --exclude /postmaster.* ~postgres/9.4/main/ backup.example.com/backup/…/base/ postgres$ psql -c "SELECT pg_stop_backup()" ~~~ #### Restauration du datadir S'assurer que PostgreSQL est éteint, et restaurer le datadir : ~~~ # rsync -a --exclude /pg_xlog/* backup.example.com/backup/…/base/ ~postgres/9.4/main/ ~~~ Attention à ne surtout pas effacer le contenu de pg_xlog/, qui peut contenir le dernier WAL courant (donc pas encore copié sur le serveur de backup). Créer un fichier recovery.conf à la racine du datadir avec le contenu suivant, puis démarrer PostgreSQL : ~~~ restore_command = 'rsync backup.example.net:/backup/…/archives/%f %p' ~~~ PostgreSQL va rejouer tous les WAL, exactement de la même manière qu'il le fait en cas de crash, puis se mettra à accepter les connexions. Il est possible de rejouer les WAL jusqu'à une certaine date (recovery_target_time) ou un certain identifiant de transaction (recovery_target_xid). ### Langage On peut installer un "langage" (PL/PGSL, PL/Perl, PL/TCP) pour une base. Exemple : ~~~ # su postgres $ createlang plpgsql production ~~~ On peut voir tous les langages disponibles via : ~~~ postgres=# select * from pg_pltemplate; tmplname | tmpltrusted | tmpldbacreate | tmplhandler | tmplvalidator | tmpllibrary | tmplacl -----------+-------------+---------------+-----------------------+-------------------+------------------+--------- plpgsql | t | t | plpgsql_call_handler | plpgsql_validator | $libdir/plpgsql | pltcl | t | t | pltcl_call_handler | | $libdir/pltcl | pltclu | f | f | pltclu_call_handler | | $libdir/pltcl | plperl | t | t | plperl_call_handler | plperl_validator | $libdir/plperl | plperlu | f | f | plperl_call_handler | plperl_validator | $libdir/plperl | plpythonu | f | f | plpython_call_handler | | $libdir/plpython | (6 rows) ~~~ ## Utilisation ### Connexion On peut maintenant "utiliser" notre base de données avec le client en ligne PostgreSQL en ligne de commande : ~~~ $ psql base login ma_base=> ~~~ Voici quelques commandes de base : ~~~ \l = liste des bases \d = liste des tables \q = quitter \h = aide SELECT version(); = version PostgreSQL SELECT current_date; = date actuelle \i fichier.sql = lit les instructions du fichier fichier.sql \d table = décrit une table (comme DESCRIBE avec MySQL) ~~~ Pour changer de base de données, deux possibilités : ~~~ => \c base; => USE base; ~~~ ### Création de table Voici les différents types de données pour les champs d'une table : ~~~ char(n) varchar(n) int real double precision date time timestamp interval ~~~ Remarque : on peut aussi définir ses propres types de données La syntaxe classique pour créer/supprimer une table : ~~~ => CREATE TABLE ma_table (col1 type, […], coln type); => DROP TABLE ma_table; ~~~ Pour la forme un petit exemple tiré de la doc de PostgreSQL : ~~~ => CREATE TABLE weather ( city varchar(80), temp_lo int, -- low temperature temp_hi int, -- high temperature prcp real, -- precipitation date date ); ~~~ Note : deux tirets -- introduisent des commentaires. Pour mettre à jour des tables : ~~~ => ALTER TABLE evosondage_admin ADD cycle varchar(25); => ALTER TABLE evosondage_admin ALTER column cycle SET not null; => ALTER TABLE evosondage_admin DROP column annee; ~~~ ### Insertion de données Insertion de tous les champs d'une table : ~~~ => INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27'); ~~~ Insertion en précisant les champs : ~~~ => INSERT INTO weather (city, temp_lo, temp_hi, prcp, date) VALUES ('San Francisco', 43, 57, 0.0, '1994-11-29'); ~~~ Insertion à partir d'un fichier externe : ~~~ => COPY weather FROM '/home/user/weather.txt'; ~~~ Note : voir http://www.postgresql.org/docs/current/interactive/sql-copy.html ### Gestion des indexes ~~~ => CREATE INDEX mytable_idx1 ON mytable(col1); => REINDEX TABLE mytable; => DROP INDEX mytable_idx1; ~~~ Pour réindexer une base de données complète : ~~~ $ psql mydb => REINDEX DATABASE mydb; ~~~ ### Extraction de données Rien ne vaut des exemples : ~~~ => SELECT * FROM weather; => SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather; => SELECT * FROM weatherWHERE city = 'San Francisco' AND prcp > 0.0; => SELECT DISTINCT city FROM weather ORDER BY city; ~~~ Avec des jointures : ~~~ => SELECT * FROM weather, cities WHERE city = name; => SELECT weather.city, weather.temp_lo, cities.location FROM weather, cities WHERE cities.name = weather.city; => SELECT * FROM weather INNER JOIN cities ON (weather.city = cities.name); => SELECT * FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name); => SELECT * FROM weather w, cities c WHERE w.city = c.name; ~~~ Avec des fonctions (Aggregate Functions) : ~~~ => SELECT max(temp_lo) FROM weather; ~~~ Attention, les "Aggregate Functions" ne peuvent être utilisées dans la clause WHERE. Ainsi la requête suivante est fausse : ~~~ => SELECT city FROM weather WHERE temp_lo = max(temp_lo); ~~~ On devra donc faire : ~~~ => SELECT city FROM weather WHERE temp_lo = (SELECT max(temp_lo) FROM weather); ~~~ On pourra bien sûr utilise GROUP BY…, HAVING…, etc. Pour envoyer le résultat dans un fichier : ~~~ => SELECT * FROM weather WHERE temp_lo=10 \g '/tmp/output' ~~~ ### Mise à jour des données Toujours avec un exemple : ~~~ => UPDATE weather SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2 WHERE date > '1994-11-28'; ~~~ ### Suppression des données Encore avec un exemple : ~~~ => DELETE FROM weather WHERE city = 'Hayward'; ~~~ Pour effacer toutes les données d'une table : ~~~ => DELETE FROM weather; ~~~ ### Schémas Par défaut, PostgreSQL utilise le schéma public mais il est possible d'utiliser d'autres schémas. * Créer un nouveau schéma : ~~~ => CREATE SCHEMA foo; ~~~ * Lister les schémas d'une base : ~~~ => \dn ~~~ * Lister les tables/indexes dans un schéma : ~~~ => \dt foo. => \di foo. ~~~ ## Monitoring * Lister les requêtes actives (PostgreSQL < 9.2) : ~~~ SELECT * FROM pg_stat_activity WHERE current_query!=''; ~~~ * lister les requêtes actives (PostgreSQL >= 9.2) : ~~~ SELECT pid, datname, usename, client_addr, query_start, waiting, query FROM pg_stat_activity WHERE state='active' ORDER by query_start; ~~~ * lister les connections en idle qui n'ont effectuées aucune requête depuis plus d'un jour : ~~~ SELECT pid, query FROM pg_stat_activity WHERE state_change < now() - interval '1d' and state = 'idle' ; ~~~ * Tuer toutes les requêtes en idle en cas de saturation : ~~~ ps aux|grep postgres|grep idle|awk '//{print $2}'|while read pid;do kill $pid;done ~~~ ### pg_top pg_top permet de lister et trier les processus clients connectés à Postgresql. Installation : ~~~ # aptitude install ptop ~~~ Puis en tant que postgres : ~~~ $ pg_top ~~~ Quelques combinaisons utiles Afficher la requête complète ~~~ "Q" + pid de la req ~~~ Plan de la requête Explain (estimation) ~~~ "E" + pid de la req ~~~ Explain Analyse (exécute) ~~~ "A" + pid de la req ~~~ Et taper ? pour la liste de toutes les commandes possibles. ## VACUUM Faire un VACUUM FULL sur toutes les bases de données : ~~~ $ vacuumdb -a -f -v ~~~ ANALYSE sur toutes les tables d'une base de données : ~~~ $ psql mydb =# ANALYZE; ~~~ ## Optimisation La configuration par défaut est fait pour s'adapter à toutes sortes de machines, elle n'est donc pas adapté en terme de performances. Nous allons voir ici quelques paramètres qui peuvent améliorer les performances de PostgreSQL. * shared_buffers : Ce paramètre détermine la quantité de mémoire dédié à PostgreSQL pour mettre en cache les données. Il est recommandé de mettre 1/4 de la quantité de RAM total de votre machine.BR /!\ Attention il est nécessaire de ne pas dépasser la valeur de la mémoire partagé du kernel, pour la changer, ajoutez kernel.shmmax = VALEUR en octets dans le sysctl.BR * max_connections : Détermine le nombre maximum de clients connectés simultanément. Ce paramètre est très important pour certains paramètres car les ressources mémoires qui sont ou seront allouées par client, il est donc suggérer d'utiliser le maximum de mémoire possible. work_memnb_clients=maxRAM.* * effective_cache_size : Ce paramètre détermine combien de mémoire devrait être disponible pour l'OS et les mémoire tampons de PostgreSQL, ce n'est pas une allocation. Cette valeur est seulement utilisé par le planificateur de requêtes de PostgreSQL pour savoir si les requêtes vont tenir en RAM ou pas. Il est recommandé de mettre 50% de la RAM voir 75%. * checkpoint_segments : PostgreSQL écrit les transactions effectuées dans un fichier de log (nommé WAL, pour Write Ahead Log). Un segment est en fait un fichier, qui fait 16Mo par défaut. Un checkpoint est fait à chaque checkpoint_segment, par défaut 3, donc 3*16 = 48Mo, ce qui peut être un goulot d'étranglement de faire des checkpoints tout les 48Mo. Il est recommandé de le mettre entre 8 (faible écritures sur les bases) et 64 (beaucoup d'écritures). 16 est une bonne valeur pour un usage standard. * checkpoint_completion_target : À partir de PostgreSQL 8.3, les checkpoint sont écrits pendant que le système commence à travailler sur le prochain checkpoint. Par défaut la valeur est de 0.5 (50%), et donc PostgreSQL s'occupe de finir le checkpoint quand le suivant est fini à 50%. Il est recommandé de fixer 90%. * autovacuum : PostgreSQL réalise de nombreuses maintenance pour nettoyer la base de données. C'est une mauvaise idée de le de désactiver complètement, mais cela peut-être utile de le désactiver temporairement, notamment en cas de forte charge. * max_fsm_pages et max_fsm_relations : /!\ Plus utilisé dans PostgreSQL >=8.4. Les paramètres sont maintenant dynamique, plus d'infos. * work_mem : Le work_mem permet d'éviter lors de grosses opérations, de swapper les données sur le disque pour les traiter. Attention il est rattaché au nombres de clients ! Par exemple un work_mem de 50Mo avec 30 utilisateurs, cela donne 1.5Go, il est donc facile de faire passer la machine en out-of-memory…BR * wal_buffers : La valeur par défaut est bien trop petite (64Ko), il est recommandé de la passer de 1Mo à 16Mo. * maintenance_work_mem : voir http://blog.guillaume.lelarge.info/index.php/post/2015/07/14/Comment-quantifier-le-maintenance_work_mem ## Benchmark pgbench est un outil intégré à PostgreSQL (dans debian, il est dans le paquet, postgresql-contrib - /usr/lib/postgresql/8.4/bin/pgbench), il permet de réaliser des tests, et d'avoir les résultats en transactions par secondes (tps). Plus d'inos sur la doc officielle. Il est recommandé de réaliser 3 fois le bench pour avoir une meilleure précision. Un petit script php permet d'automatiser les benchs ~~~ # aptitude install php5-cli postgresql-contrib $ wget http://pastebin.com/download.php?i=hD570TgL -O /tmp/script.php $ su postgres $ createdb -O postgres -E UNICODE pgbench $ /usr/lib/postgresql/8.4/bin/pgbench -i pgbench -s 50 ~~~ ### Exemple avant optimisation ~~~ $ php -f script.php Shared Memory Max is 3,072.00Mb PostgreSQL is using 10.57Mb Testing: 5 clients with 5 transactions (5 samples) TPS Min 543.218461; Max: 666.471168; Avg: 590.9413884; Dev: 48.7702658268 CTPS Min: 702.760443; Max: 926.406285; Avg: 788.2504666; Dev: 89.6348872298 Testing: 5 clients with 10 transactions (5 samples) TPS Min 132.604187; Max: 808.211428; Avg: 644.4933226; Dev: 288.384840931 CTPS Min: 136.534056; Max: 973.652951; Avg: 765.8912782; Dev: 355.324132181 Testing: 5 clients with 50 transactions (5 samples) TPS Min 915.127422; Max: 1042.774615; Avg: 987.7306472; Dev: 47.8906556447 CTPS Min: 951.916780; Max: 1090.940827; Avg: 1030.9061366; Dev: 52.042571476 Testing: 10 clients with 5 transactions (5 samples) TPS Min 598.802395; Max: 720.990930; Avg: 677.7113778; Dev: 48.4403117914 CTPS Min: 797.143039; Max: 1033.399471; Avg: 944.3966004; Dev: 90.8906145724 Testing: 10 clients with 10 transactions (5 samples) TPS Min 665.552975; Max: 935.007620; Avg: 799.1810664; Dev: 126.329870233 CTPS Min: 774.287462; Max: 1157.742402; Avg: 964.7010562; Dev: 179.888588017 Testing: 10 clients with 50 transactions (5 samples) TPS Min 26.782745; Max: 1040.286120; Avg: 549.5094934; Dev: 486.121295095 CTPS Min: 26.812935; Max: 1086.554969; Avg: 570.8430692; Dev: 506.835600619 pg_benchmark executed 30 tests in about 39 seconds ~~~ ### Exemple après optimisation ~~~ Shared Memory Max is 3,072.00Mb PostgreSQL is using 10.57Mb Testing: 5 clients with 5 transactions (5 samples) TPS Min 668.878425; Max: 716.147698; Avg: 692.1704534; Dev: 18.0051424274 CTPS Min: 958.662474; Max: 1050.199538; Avg: 1002.8300562; Dev: 34.217782456 Testing: 5 clients with 10 transactions (5 samples) TPS Min 793.550025; Max: 989.922588; Avg: 909.7281046; Dev: 73.6959734873 CTPS Min: 974.601875; Max: 1265.086152; Avg: 1146.0283372; Dev: 112.187073149 Testing: 5 clients with 50 transactions (5 samples) TPS Min 1051.069358; Max: 1226.031092; Avg: 1126.4953152; Dev: 63.4721625573 CTPS Min: 1105.519638; Max: 1297.420728; Avg: 1186.3068702; Dev: 69.9807788556 Testing: 10 clients with 5 transactions (5 samples) TPS Min 622.091721; Max: 781.677480; Avg: 729.4070334; Dev: 64.9725527355 CTPS Min: 846.596681; Max: 1169.235086; Avg: 1062.2111624; Dev: 131.355197786 Testing: 10 clients with 10 transactions (5 samples) TPS Min 945.930607; Max: 1084.363479; Avg: 997.8187306; Dev: 57.4096186704 CTPS Min: 1182.886005; Max: 1401.993635; Avg: 1264.4000858; Dev: 91.9101739593 Testing: 10 clients with 50 transactions (5 samples) TPS Min 1210.334319; Max: 1467.351431; Avg: 1341.577537; Dev: 98.2366159289 CTPS Min: 1277.331705; Max: 1563.379401; Avg: 1422.1924606; Dev: 109.288692112 pg_benchmark executed 30 tests in about 5 seconds ~~~ ## Réplication Plusieurs solutions de réplication plus ou moins avancées existent avec PostgreSQL : * PITR, Point In Time Recovery : copie des logs de transaction (WAL) sur un serveur distant pour archivage. Ils peuvent ensuite être rejoué jusqu'à un point précis en cas de perte de donnée par exemple. * Warm Standby : les WAL sont copiés sur un second serveur sur lequel tourne un PostgreSQL en mode recovery constant. Chaque segment reçu est rejoué par PostgreSQL. Il est alors prêt à prendre le relais en cas de panne sur le serveur maître. * Hot Standby : le principe est le même que pour le Warm Standby, mais le serveur esclave peut être interrogé en lecture. * Streaming Replication : ce ne sont plus les logs qui sont envoyés (qui nécessite un certain temps de propagation, car le fichier est transféré une fois plein), mais les données sont transféré immédiatement par un processus dédié (walsender) dans une connexion réseau établie avec le serveur esclave. Contrairement aux autres solutions, cela nécessite une légère charge supplémentaire par esclave sur le maître pour faire tourner le processus walsender.