PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Réglage des opérations d'entrée/sortie (E/S) pour PostgreSQL

PostgreSQL est l'une des bases de données open source les plus populaires au monde et a des implémentations réussies dans plusieurs environnements critiques dans divers domaines, en utilisant des applications OLTP haut de gamme en temps réel effectuant des millions et des milliards de transactions par jour. Les E/S PostgreSQL sont assez fiables, stables et performantes sur à peu près n'importe quel matériel, y compris le cloud.

Pour garantir que les bases de données fonctionnent à l'échelle attendue avec les temps de réponse attendus, une certaine ingénierie des performances est nécessaire. Eh bien, la réalisation de bonnes performances de base de données dépend de divers facteurs. Les performances de la base de données peuvent se détériorer pour diverses raisons, telles que le dimensionnement de l'infrastructure, une stratégie de maintenance de base de données inefficace, un code SQL médiocre ou des processus de base de données mal configurés qui ne parviennent pas à utiliser toutes les ressources disponibles :processeur, mémoire, bande passante réseau et E/S disque.

Qu'est-ce qui peut entraîner une dégradation des performances de la base de données ?

  • Requêtes mal écrites avec de mauvaises jointures, une mauvaise logique, etc. qui consomment beaucoup de CPU et de mémoire
  • Requêtes effectuant des analyses de table complète sur de grandes tables en raison d'une indexation incorrecte
  • Mauvaise maintenance de la base de données sans statistiques appropriées en place
  • Planification inefficace des capacités entraînant une infrastructure mal dimensionnée
  • Conception logique et physique incorrecte
  • Aucune mise en commun des connexions en place, ce qui oblige les applications à établir un grand nombre de connexions de manière incontrôlable

Il y a donc beaucoup de domaines potentiels qui peuvent causer des problèmes de performances. L'un des domaines importants sur lesquels je voudrais me concentrer dans ce blog est de savoir comment régler les performances d'E/S (entrée/sortie) de PostgreSQL. Le réglage des opérations d'entrée/sortie de PostgreSQL est essentiel, en particulier dans un environnement hautement transactionnel comme OLTP ou dans un environnement d'entreposage de données avec une analyse de données complexe sur des ensembles de données de grande taille.

La plupart du temps, les problèmes de performances de la base de données sont principalement dus à des E/S élevées. Cela signifie que les processus de base de données passent plus de temps à écrire ou à lire sur le disque. Toute opération de données en temps réel est liée aux E/S, il est impératif de s'assurer que la base de données est adaptée aux E/S. Dans ce blog, je me concentrerai sur les problèmes d'E/S courants que les bases de données PostgreSQL peuvent rencontrer dans les environnements de production en temps réel.

Réglage des E/S PostgreSQL

Le réglage des E/S PostgreSQL est impératif pour créer une architecture de base de données hautement performante et évolutive. Examinons divers facteurs ayant une incidence sur les performances d'E/S :

  • Indexation
  • Partitionnement
  • Points de contrôle
  • VIDE, ANALYSER (avec FILLFACTOR)
  • Autres problèmes d'E/S
  • E/S PostgreSQL sur le cloud
  • Outils

Indexation

L'indexation est l'une des principales techniques de réglage qui joue un rôle essentiel dans l'amélioration des performances d'E/S de la base de données. Cela s'applique à n'importe quelle base de données vraiment. PostgreSQL prend en charge divers types d'index qui peuvent accélérer considérablement les opérations de lecture, ce qui améliore l'évolutivité des applications. Bien que la création d'index soit assez simple et directe, il est essentiel que les DBA et les développeurs sachent quel type d'index choisir et sur quelles colonnes. Ce dernier est basé sur divers facteurs tels que la complexité des requêtes, le type de données, la cardinalité des données, le volume d'écritures, la taille des données, l'architecture du disque, l'infrastructure (cloud public, cloud privé ou sur site), etc.

Bien que l'indexation puisse considérablement améliorer les performances de lecture des requêtes, elle peut également ralentir les écritures atteignant les colonnes indexées. Prenons un exemple :

Impact des index sur les opérations READ

Une table appelée emp avec environ 1 million de lignes.

LIRE les performances sans index

postgres=# select * from emp where eid=10;

 eid | ename    | peid | did  |    doj
-----+---------------+--------+------+------------
  10 | emp        |          |   1   | 2018-06-06
(1 row)
 
Time: 70.020 ms => took about 70+ milli-seconds to respond with on row

LIRE les performances avec un index

Mettons un index sur la colonne eid et voyons la différence

postgres=# create index indx001 on emp ( eid );
CREATE INDEX

postgres=# select * from emp where eid=10;

 eid | ename  | peid | did |    doj
------+-------------+-------+------+------------
  10 | emp      |          |   1   | 2018-06-06
(1 row)
 
Time: 0.454 ms =>  0.4+ milli-seconds!!! thats a huge difference - isn’t it?

L'indexation est donc importante.

Impact des index sur les opérations WRITE

Les index ralentissent les performances des écritures. Bien que les index aient un impact sur tous les types d'opérations d'écriture, examinons une analyse de l'impact des index sur les INSERTs

Insérer 1 million de lignes dans une table sans index

postgres=# do $$
postgres$# declare
postgres$# i integer;
postgres$# begin
postgres$# for i in 1..1000000 loop
postgres$# insert into emp values (i,'emp',null,1,current_date);
postgres$# end loop;
postgres$# end $$;
DO

Time: 4818.470 ms (00:04.818) => Takes about 4.8 seconds

Insérer le même million de lignes avec un Index

Créons d'abord un Index

postgres=# create index indx001 on emp ( eid );
CREATE INDEX

postgres=# do $$
postgres$# declare
postgres$# i integer;
postgres$# begin
postgres$# for i in 1..1000000 loop
postgres$# insert into emp values (i,'emp',null,1,current_date);
postgres$# end loop;
postgres$# end $$;
DO

Time: 7825.494 ms (00:07.825) =>  Takes about 7.8 seconds

Ainsi, comme nous pouvons le constater, le temps d'insertion a augmenté de 80 % avec un seul index et peut prendre beaucoup plus de temps pour se terminer lorsqu'il y a plusieurs index. Cela peut s'aggraver lorsqu'il existe des index basés sur des fonctions. C'est avec cela que les DBA doivent vivre ! Les index augmenteront les performances d'écriture. Il existe cependant des moyens de résoudre ce problème, qui dépend de l'architecture du disque. Si le serveur de base de données utilise plusieurs systèmes de fichiers sur disque, les index et les tables peuvent être placés sur plusieurs espaces de table situés sur plusieurs systèmes de fichiers sur disque. De cette façon, de meilleures performances d'E/S peuvent être obtenues.

CONSEILS de gestion des index

  • Comprendre le besoin d'index. L'indexation intelligente est essentielle.
  • Évitez de créer plusieurs index, et certainement pas d'index inutiles, cela peut vraiment dégrader les performances d'écriture.
  • Surveillez l'utilisation des index et supprimez tous les index inutilisés.
  • Lorsque les colonnes indexées sont soumises à des modifications de données, les index sont également gonflés. Donc, réorganisez régulièrement les index.

Partitionnement

Une stratégie de partitionnement efficace peut réduire considérablement les problèmes de performances d'E/S. Les grandes tables peuvent être partitionnées en fonction de la logique métier. PostgreSQL prend en charge le partitionnement de table. Bien qu'il ne prenne pas entièrement en charge toutes les fonctionnalités pour le moment, il ne peut aider que dans certains cas d'utilisation en temps réel. Dans PostgreSQL, les tables enfants partitionnées sont complètement individuelles à la table maître qui est un goulot d'étranglement. Par exemple, les contraintes créées sur la table maître ne peuvent pas être automatiquement héritées sur les tables enfants.

Cependant, du point de vue de l'équilibrage des E/S, le partitionnement peut vraiment aider. Toutes les partitions enfants peuvent être réparties sur plusieurs espaces de table et systèmes de fichiers de disque. Les requêtes avec une plage de dates dans la clause "where" frappant la table, partitionnée en fonction de la plage de dates, peuvent bénéficier du partitionnement en analysant simplement une ou deux partitions au lieu de la table complète.

Points de contrôle

Les points de contrôle définissent l'état cohérent de la base de données. Ils sont critiques et il est important que les points de contrôle se produisent suffisamment régulièrement pour garantir que les modifications de données sont enregistrées de manière permanente sur le disque et que la base de données est dans un état cohérent tout le temps. Cela étant dit, une configuration incorrecte des points de contrôle peut entraîner des problèmes de performances d'E/S. Les administrateurs de base de données doivent être méticuleux quant à la configuration des points de contrôle pour s'assurer qu'il n'y a pas de pic d'E/S. Cela dépend également de la qualité des disques et de la qualité de l'architecture des fichiers de données.

Que fait le point de contrôle ?

En termes simples, les points de contrôle assureront :

  • Toutes les données validées sont écrites dans les fichiers de données sur le disque.
  • les fichiers obstrués sont mis à jour avec le statut de validation.
  • Les fichiers journaux des transactions dans le répertoire pg_xlog (maintenant pg_wal) sont recyclés.

Cela explique à quel point les points de contrôle intensifs d'E / S sont. Il y a des paramètres dans postgresql.conf qui peuvent être configurés/réglés pour contrôler le comportement des points de contrôle et ces paramètres sont max_wal_size, min_wal_size, checkpoint_timeout et checkpoint_completion_target. Ces paramètres décideront de la fréquence à laquelle les points de contrôle doivent se produire et du délai dans lequel les points de contrôle doivent se terminer.

Comment comprendre quelle configuration est la meilleure pour les points de contrôle ? Comment les accorder ?

Voici quelques conseils :

  • Évaluer la base de données TPS. Évaluez le volume total de transactions effectuées dans la base de données en un jour ouvrable et identifiez également à quelle heure le plus grand nombre de transactions atteint la base de données.
  • Discutez régulièrement avec les développeurs d'applications et d'autres équipes techniques pour comprendre les statistiques du taux de transaction de la base de données ainsi que la croissance future des transactions.
  • Cela peut également être fait à partir de la fin de la base de données :
    • Surveillez la base de données et évaluez le nombre de transactions effectuées au cours de la journée. Cela peut être fait en interrogeant les tables de pgcatalog comme pg_stat_user_tables.

    • Évaluer le nombre de fichiers d'archive wal générés par jour

    • Surveillez pour comprendre comment les points de contrôle fonctionnent en activant le paramètre log_checkpoints

      2018-06-06 15:03:16.446 IST [2111] LOG:  checkpoint starting: xlog
      2018-06-06 15:03:22.734 IST [2111] LOG:  checkpoint complete: wrote 12112 buffers (73.9%); 0 WAL file(s) added, 0 removed, 25 recycled; write=6.058 s, sync=0.218 s, total=6.287 s; sync files=4, longest=0.178 s, average=0.054 s; distance=409706 kB, estimate=412479 kB
    • Déterminez si la configuration actuelle du point de contrôle est suffisante pour la base de données. Configurez le paramètre checkpoint_warning (configuré par défaut à 30 secondes) pour voir les avertissements ci-dessous dans les fichiers journaux postgres.

      2018-06-06 15:02:42.295 IST [2111] LOG:  checkpoints are occurring too frequently (11 seconds apart)
      2018-06-06 15:02:42.295 IST [2111] HINT:  Consider increasing the configuration parameter "max_wal_size".

Que signifie l'avertissement ci-dessus ?

Les points de contrôle se produisent généralement chaque fois que max_wal_size (1 Go par défaut, ce qui signifie 64 fichiers WAL) de fichiers journaux est rempli ou lorsque checkpoint_timeout (toutes les 5 minutes par défaut) est atteint. L'avertissement ci-dessus signifie que max_wal_size configuré n'est pas adéquat et que les points de contrôle se produisent toutes les 11 secondes, ce qui signifie que 64 fichiers WAL dans le répertoire PG_WAL sont remplis en seulement 11 secondes, ce qui est trop fréquent. En d'autres termes, s'il y a des transactions moins fréquentes, les points de contrôle se produiront toutes les 5 minutes. Ainsi, comme le suggère l'indice, augmentez le paramètre max_wal_size à une valeur plus élevée, le paramètre max_min_size peut être augmenté à la même valeur ou à une valeur inférieure à l'ancien.

Un autre paramètre critique à prendre en compte du point de vue des performances d'E/S est checkpoint_completion_target qui est configuré par défaut sur 0,5.

checkpoint_completion_target =0,5 x checkpoint_timeout =2,5 minutes

Cela signifie que les points de contrôle ont 2,5 minutes pour synchroniser les blocs sales sur le disque. 2,5 minutes suffisent-elles ? Cela doit être évalué. Si le nombre de blocs sales à écrire est très élevé, alors 2,5 minutes peuvent sembler très très agressifs et c'est alors qu'un pic d'E/S peut être observé. La configuration du paramètre Completion_target doit être effectuée en fonction des valeurs max_wal_size et checkpoint_timeout. Si ces paramètres sont augmentés à une valeur supérieure, envisagez d'augmenter checkpoint_completion_target en conséquence.

VIDE, ANALYSER (avec FILLFACTOR)

VACUUM est l'une des fonctionnalités les plus puissantes de PostgreSQL. Il peut être utilisé pour supprimer les ballonnements (espace fragmenté) dans les tables et les index, et est généré par les transactions. La base de données doit être soumise à VACUUM régulièrement pour assurer une maintenance saine et de meilleures performances. Encore une fois, ne pas VACUUMer régulièrement la base de données peut entraîner de graves problèmes de performances. ANALYZE doit être exécuté avec VACUUM (VACUUM ANALYZE) pour garantir des statistiques à jour pour le planificateur de requêtes.

L'ANALYSE DU VIDE peut être effectuée de deux manières :manuelle, automatique ou les deux. Dans un environnement de production en temps réel, c'est généralement les deux. Le VACUUM automatique est activé par le paramètre « autovacuum » qui est configuré par défaut sur « on ». Avec l'autovacuum activé, PostgreSQL démarre automatiquement VACUUMing les Tables périodiquement. Les tables candidates nécessitant un aspirateur sont récupérées par des processus d'autovacuum basés sur divers seuils définis par divers paramètres d'autovacuum *, ces paramètres peuvent être modifiés / ajustés pour garantir que les ballonnements des tables sont effacés périodiquement. Regardons quelques paramètres et leur utilisation -

Paramètres de vide automatique

autovacuum=on Ce paramètre est utilisé pour activer/désactiver l'autovacuum. La valeur par défaut est "activé".
log_autovacuum_min_duration =-1 Enregistre la durée du processus d'autovacuum. Ceci est important pour comprendre la durée d'exécution du processus d'autovacuum.
autovacuum_max_workers =3 Nombre de processus de vide automatique nécessaires. Cela dépend de l'agressivité des transactions de base de données et du nombre de processeurs que vous pouvez proposer pour les processus de vide automatique.
autovacuum_naptime =1 min Temps de repos de l'autovacuum entre les cycles d'autovacuum.

Paramètres définissant le seuil de démarrage du processus Autovacuum

Les tâches de vide automatique démarrent lorsqu'un certain seuil est atteint. Vous trouverez ci-dessous les paramètres qui peuvent être utilisés pour définir un certain seuil, sur la base duquel le processus d'autovacuum démarrera.

autovacuum_vacuum_threshold =50 Le tableau sera aspiré lorsqu'un minimum de 50 lignes seront mises à jour/supprimées dans un tableau.
autovacuum_analyze_threshold =50 Le tableau sera analysé lorsqu'un minimum de 50 lignes seront mises à jour/supprimées dans un tableau.
autovacuum_vacuum_scale_factor =0.2 Le tableau sera aspiré lorsqu'au moins 20 % des lignes sont mises à jour/supprimées dans un tableau.
autovacuum_analyze_scale_factor =0.1 Le tableau sera aspiré lorsqu'au moins 10 % des lignes sont mises à jour/supprimées dans un tableau.

Les paramètres au-dessus du seuil peuvent être modifiés en fonction du comportement de la base de données. Les administrateurs de base de données devront analyser et identifier les tables actives et s'assurer que ces tables sont aspirées aussi fréquemment que possible pour garantir de bonnes performances. Arriver à une certaine valeur pour ces paramètres pourrait être un défi dans un environnement à transactions élevées, dans lequel des changements de données se produisent toutes les secondes. J'ai souvent remarqué que les processus d'autovacuum prennent assez de temps à se terminer, finissant par consommer trop de ressources dans les systèmes de production.

Je suggérerais de ne pas dépendre complètement du processus d'autovacuum, la meilleure façon est de programmer un travail nocturne d'ANALYSE DU VIDE afin que la charge sur l'autovacuum soit réduite. Pour commencer, envisagez de vider manuellement les grandes tables avec un taux de transaction élevé.

VIDE PLEIN

VACUUM FULL aide à récupérer l'espace gonflé dans les tables et les index. Cet utilitaire ne peut pas être utilisé lorsque la base de données est en ligne car il verrouille la table. Les tables doivent être soumises à VACUUM FULL uniquement lorsque les applications sont fermées. Les index seront également réorganisés avec les tables pendant VACUUM FULL.

Jetons un coup d'œil à l'impact de VACUUM ANALYZE

Bloats :comment identifier les ballonnements ? Quand les ballonnements sont-ils générés ?

Voici quelques tests :

J'ai une table de taille 1 Go avec 10 millions de lignes.

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

 ?column? 
----------------
        1

postgres=# select count(*) From pgbench_accounts ;
  count   
-----------------
 10000000

Regardons l'impact des ballonnements sur une simple requête :select * from pgbench_accounts;

Vous trouverez ci-dessous le plan d'explication de la requête :

postgres=# explain analyze select * from pgbench_accounts;

QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on pgbench_accounts  (cost=0.00..263935.00 rows=10000000 width=97) 
 (actual time=0.033..1054.257 rows=10000000 loops=1)
 Planning time: 0.255 ms
 Execution time: 1494.448 ms

Maintenant, mettons à jour toutes les lignes du tableau et voyons l'impact de la requête SELECT ci-dessus.

postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000

postgres=# select count(*) From pgbench_accounts ;
  count   
-----------------
 10000000

Vous trouverez ci-dessous le PLAN EXPLAIN de la requête après l'exécution de UPDATE.

postgres=# explain analyze select * from pgbench_accounts;

QUERY PLAN                                                             
----------------------------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on pgbench_accounts  (cost=0.00..527868.39 rows=19999939 width=97) 
 (actual time=404.474..1520.175 rows=10000000 loops=1)
 Planning time: 0.051 ms
 Execution time: 1958.532 ms

La taille de la table est passée à 2 Go après la MISE À JOUR

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

 ?column? 
-----------------
        2

Si vous pouvez observer et comparer les coûts du plan EXPLAIN précédent, il y a une énorme différence. Le coût a augmenté d'une grande marge. Plus important encore, si vous observez attentivement, le nombre de lignes (un peu plus de 19 millions) analysées après la MISE À JOUR est plus élevé, soit près de deux fois le nombre réel de lignes existantes (10 millions). Cela signifie que le nombre de lignes gonflées est de plus de 9 millions et que le temps réel a également augmenté et que le temps d'exécution est passé de 1,4 seconde à 1,9 seconde.

Donc, c'est l'impact de ne pas VACUUMer la TABLE après la MISE À JOUR. Les numéros EXPLAIN PLAN ci-dessus signifient précisément que le tableau est gonflé.

Comment identifier si le tableau est gonflé ? Utilisez le module de contribution pgstattuple :

postgres=# select * from pgstattuple('pgbench_accounts');
 table_len  | tuple_count | tuple_len  | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent 
------------+-------------+------------+---------------+------------------+----------------+--------------------+------------+--------------
 2685902848 |    10000000 | 1210000000 |         45.05 |          9879891 |     1195466811 |              44.51 |   52096468 |         1.94

Le nombre ci-dessus indique que la moitié de la table est gonflée.

Laissez-nous VACUUM ANALYSER le tableau et voyez l'impact maintenant :

postgres=# VACUUM ANALYZE pgbench_accounts ;
VACUUM

postgres=# explain analyze select * from pgbench_accounts;

QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------
 Seq Scan on pgbench_accounts  (cost=0.00..428189.05 rows=10032005 width=97) 
 (actual time=400.023..1472.118 rows=10000000 loops=1)
 Planning time: 4.374 ms
 Execution time: 1913.541 ms

Après VACUUM ANALYZE, les chiffres de coût ont diminué. Maintenant, le nombre de lignes analysées s'élève à près de 10 millions, et le temps réel et le temps d'exécution n'ont pas beaucoup changé. En effet, bien que les ballonnements dans la table aient disparu, la taille de la table à scanner reste la même. Ci-dessous se trouve la sortie de pgstattuple post VACUUM ANALYZE.

postgres=# select * from pgstattuple('pgbench_accounts');

 table_len  | tuple_count | tuple_len  | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent 
------------+-------------+------------+---------------+------------------+----------------+--------------------+------------+--------------
 2685902848 |    10000000 | 1210000000 |         45.05 |             0 |              0 |                  0 | 1316722516 |        49.02

Le nombre ci-dessus indique que tous les ballonnements (tuples morts) ont disparu.

Examinons l'impact de VACUUM FULL ANALYZE et voyons ce qui se passe :

postgres=# vacuum full analyze pgbench_accounts ;
VACUUM

postgres=# explain analyze select * from pgbench_accounts;

                            QUERY PLAN                                                            
---------------------------------------------------------------------------
 Seq Scan on pgbench_accounts  (cost=0.00..263935.35 rows=10000035 width=97) 
(actual time=0.015..1089.726 rows=10000000 loops=1)
 Planning time: 0.148 ms
 Execution time: 1532.596 ms

Si vous observez, le temps réel et les nombres de temps d'exécution sont similaires aux nombres avant UPDATE. De plus, la taille du tableau est maintenant passée de 2 Go à 1 Go.

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

 ?column? 
-----------------
        1

C'est l'impact de VACUUM FULL.

FACTEUR DE REMPLISSAGE

FILLFACTOR est un attribut très important qui peut faire une réelle différence dans la stratégie de maintenance de la base de données au niveau des tables et des index. Cette valeur indique la quantité d'espace à utiliser par les INSERT dans un bloc de données. La valeur FILLFACTOR est par défaut de 100 %, ce qui signifie que les INSERTs peuvent utiliser tout l'espace disponible dans un bloc de données. Cela signifie également qu'aucun espace n'est disponible pour les UPDATE. Cette valeur peut être réduite à une certaine valeur pour les tables fortement mises à jour.

Ce paramètre peut être configuré pour chaque table et un index. Si FILLFACTOR est configuré à la valeur optimale, vous pouvez également voir une réelle différence dans les performances de VACUUM et les performances des requêtes. En bref, les valeurs FILLFACTOR optimales garantissent qu'un nombre inutile de blocs ne sont pas alloués.

Regardons le même exemple ci-dessus -

Le tableau a un million de lignes

postgres=# select count(*) From pgbench_accounts ;
  count   
-----------------
 10000000

Avant la mise à jour, la taille de la table est de 1 Go

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

?column? 
--------
   1

postgres=# update pgbench_accounts set abalance=1;
UPDATE 10000000

Après mise à jour, la taille de la table est passée à 2 Go après la MISE À JOUR

postgres=# select pg_relation_size('pgbench_accounts')/1024/1024/1024;

?column? 
---------
    2

Cela signifie que le nombre de blocs alloués à la table a augmenté de 100 %. Si le FILLFACTOR a été configuré, la taille de la table peut ne pas avoir augmenté de cette marge.

Comment savoir quelle valeur configurer pour FILLFACTOR ?

Tout dépend des colonnes mises à jour et de la taille des colonnes mises à jour. En général, il serait bon d'évaluer la valeur FILLFACTOR en la testant dans les bases de données UAT. Si les colonnes mises à jour représentent, par exemple, 10 % de l'ensemble du tableau, envisagez de configurer fillfactor à 90 % ou 80 %.

Remarque importante :
Si vous modifiez la valeur FILLFACTOR pour la table existante avec les données, vous devrez effectuer un VACUUM FULL ou une réorganisation de la table pour vous assurer que la valeur FILLFACTOR est effective pour les données existantes.

CONSEILS POUR PASSER L'ASPIRATEUR

  • Comme indiqué ci-dessus, envisagez d'exécuter la tâche VACUUM ANALYZE manuellement tous les soirs sur les tables très utilisées, même lorsque la fonction d'autovacuum est activée.
  • Envisagez d'exécuter VACUUM ANALYZE sur les tables après l'insertion en bloc. Ceci est important car beaucoup pensent que VACUUMing n'est peut-être pas nécessaire après les INSERTs.
  • Surveiller pour s'assurer que les tables très actives sont régulièrement VACUUMées en interrogeant la table pg_stat_user_tables.
  • Utilisez le module contrib pg_stattuple pour identifier la taille de l'espace gonflé dans les segments de table.
  • L'utilitaire VACUUM FULL ne peut pas être utilisé sur les systèmes de base de données de production. Envisagez d'utiliser des outils comme pg_reorg ou pg_repack qui aideront à réorganiser les tables et les index en ligne sans verrous.
  • Assurez-vous que le processus AUTOVACUUM s'exécute plus longtemps pendant les heures ouvrables (fort trafic).
  • Activez le paramètre log_autovacuum_min_duration pour consigner les horaires et la durée des processus AUTOVACUUM.
  • Il est important de s'assurer que FILLFACTOR est configuré sur une valeur optimale sur les tables et les index à transactions élevées.
Téléchargez le livre blanc aujourd'hui PostgreSQL Management &Automation with ClusterControlDécouvrez ce que vous devez savoir pour déployer, surveiller, gérer et faire évoluer PostgreSQLTélécharger le livre blanc

Autres problèmes d'E/S

Tri de disque

Les requêtes effectuant un tri sont une autre occurrence courante dans les bases de données de production en temps réel et la plupart d'entre elles ne peuvent être évitées. Les requêtes utilisant des clauses telles que GROUP BY, ORDER BY, DISTINCT, CREATE INDEX, VACUUM FULL, etc. effectuent un tri et le tri peut avoir lieu sur le disque. Le tri a lieu dans la mémoire si la sélection et le tri sont effectués sur la base de colonnes indexées. C'est là que les indices composites jouent un rôle clé. Les index sont mis en cache de manière agressive dans la mémoire. Sinon, s'il s'avérait nécessaire de trier les données sur le disque, les performances seraient considérablement ralenties.

Pour s'assurer que le tri s'effectue en mémoire, le paramètre work_mem peut être utilisé. Ce paramètre peut être configuré à une valeur telle que tout le tri puisse se faire en mémoire. Le principal avantage de ce paramètre est que, outre sa configuration dans postgresql.conf, il peut également être configuré au niveau de la session, de l'utilisateur ou de la base de données. Quelle doit être la valeur work_mem ? Comment savoir quelles requêtes effectuent le tri du disque ? Comment surveiller les requêtes effectuant un tri de disque sur une base de données de production en temps réel ?

La réponse est - configurez le paramètre log_temp_files sur une certaine valeur. La valeur est en octets, une valeur de 0 enregistre tous les fichiers temporaires (ainsi que leurs tailles) générés sur le disque en raison du tri du disque. Une fois le paramètre configuré, vous pourrez voir les messages suivants dans les fichiers journaux

2018-06-07 22:48:02.358 IST [4219] LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4219.0", size 200425472
2018-06-07 22:48:02.358 IST [4219] STATEMENT:  create index bid_idx on pgbench_accounts(bid);
2018-06-07 22:48:02.366 IST [4219] LOG:  duration: 6421.705 ms  statement: create index bid_idx on pgbench_accounts(bid);

Le message ci-dessus signifie que la requête CREATE INDEX effectuait un tri de disque et a généré un fichier de taille 200425472 octets, soit plus de 191 Mo. Cela signifie précisément que le paramètre work_mem doit être configuré sur 191+ Mo ou plus pour que cette requête particulière effectue le tri de la mémoire.

Eh bien, pour les requêtes d'application, le paramètre work_mem ne peut être configuré qu'au niveau de l'utilisateur. Avant de le faire, méfiez-vous du nombre de connexions que l'utilisateur établit avec la base de données et du nombre de requêtes de tri exécutées par cet utilisateur. Parce que PostgreSQL essaie d'allouer work_mem à chaque processus (effectuant un tri) dans chaque connexion, ce qui pourrait potentiellement affamer la mémoire sur le serveur de base de données.

Disposition du système de fichiers de la base de données

La conception d'une disposition de système de fichiers de base de données efficace et propice aux performances est importante du point de vue des performances et de l'évolutivité. Surtout, cela ne dépend pas de la taille de la base de données. En général, la perception est que les bases de données de grande taille auront besoin d'une architecture de disque haute performance, ce qui n'est PAS vrai. Même si la taille de la base de données est de 50 Go, vous aurez peut-être besoin d'une bonne architecture de disque. Et cela peut ne pas être possible sans encourir des coûts supplémentaires.

Voici quelques CONSEILS pour la même :

  • Assurez-vous que la base de données comporte plusieurs espaces de table, avec des tables et des index regroupés en fonction des taux de transaction.
  • L'espace de table doit être placé sur plusieurs systèmes de fichiers de disque pour des E/S équilibrées. Cela garantira également que plusieurs processeurs entrent en jeu pour effectuer des transactions sur plusieurs disques.
  • Envisagez de placer le répertoire pg_xlog ou pg_wal sur un disque séparé sur une base de données à transactions élevées.
  • Assurez-vous que les paramètres *_cost sont configurés en fonction de l'infrastructure
  • Utilisez iostat, mpstat et d'autres outils de surveillance des E/S pour comprendre les statistiques d'E/S sur tous les disques et concevoir/gérer les objets de la base de données en conséquence.

PostgreSQL sur le cloud

L'infrastructure est essentielle pour de bonnes performances de base de données. Les stratégies d'ingénierie des performances diffèrent en fonction de l'infrastructure et de l'environnement. Une attention particulière doit être portée aux bases de données PostgreSQL hébergées dans le cloud. L'analyse comparative des performances des bases de données hébergées sur des serveurs barebone physiques dans un centre de données local peut être entièrement différente de celle des bases de données hébergées dans le cloud public.

En général, les instances cloud peuvent être un peu plus lentes et les benchmarks diffèrent considérablement, notamment en termes d'E/S. Effectuez toujours des vérifications de latence d'E/S avant de choisir/créer une instance cloud. À ma grande surprise, j'ai appris que les performances des instances cloud peuvent également varier en fonction des régions, même si elles proviennent du même fournisseur de cloud. Pour expliquer cela plus en détail, une instance cloud avec les mêmes spécifications construites dans deux régions différentes pourrait vous donner des résultats de performances différents.

Chargement de données en masse

Les opérations de chargement de données en masse hors ligne sont assez courantes dans le monde des bases de données. Ils peuvent générer une charge d'E/S importante, qui à son tour ralentit les performances de chargement des données. J'ai fait face à de tels défis dans mon expérience en tant que DBA. Souvent, le chargement des données devient terriblement lent et doit être réglé. Voici quelques conseils. Attention, ceux-ci s'appliquent uniquement aux opérations de chargement de données hors ligne et ne peuvent pas être pris en compte pour le chargement de données sur une base de données de production en direct.

  • Étant donné que la plupart des opérations de chargement de données sont effectuées en dehors des heures de bureau, assurez-vous que les paramètres suivants sont configurés pendant le chargement de données :
    • Configurez des valeurs liées aux points de contrôle suffisamment grandes pour que les points de contrôle ne causent aucun problème de performances.
    • Désactivez full_page_write
    • Désactiver l'archivage wal
    • Configurer le paramètre synchronous_commit sur "off"
    • Supprimer les contraintes et les index pour les tables soumises au chargement des données (les contraintes et les index peuvent être recréés après le chargement des données avec une valeur work_mem plus grande)
    • Si vous chargez les données à partir d'un fichier CSV, une maintenance_work_mem plus importante peut vous donner de bons résultats.
    • Bien qu'il y ait un avantage significatif en termes de performances, NE PAS désactiver le paramètre fsync car cela pourrait entraîner une corruption des données.

CONSEILS pour l'analyse des performances du cloud

  • Effectuez des tests approfondis de latence d'E/S à l'aide de pgbench. D'après mon expérience, j'ai obtenu des résultats de performances assez ordinaires lors des vérifications de latence du disque dans le cadre de l'évaluation TPS. Il y avait des problèmes avec les performances du cache sur certaines instances de cloud public. Cela aidera à choisir les spécifications appropriées pour l'instance cloud choisie pour les bases de données.
  • Les instances cloud peuvent fonctionner différemment d'une région à l'autre. Une instance cloud avec certaines spécifications dans une région peut donner des résultats de performances différents par rapport à une instance cloud avec les mêmes spécifications dans une autre région. Mes tests pgbench exécutés sur plusieurs instances de cloud (toutes les mêmes spécifications avec le même fournisseur de cloud) dans différentes régions m'ont donné des résultats différents sur certaines d'entre elles. Ceci est particulièrement important lorsque vous migrez vers le cloud.
  • Les performances des requêtes sur le cloud peuvent nécessiter une approche de réglage différente. Les administrateurs de base de données devront utiliser les paramètres *_cost pour s'assurer que des plans d'exécution de requête sains sont générés.

Tools to Monitor PostgreSQL Performance

There are various tools to monitor PostgreSQL performance. Let me highlight some of those.

  • pg_top is a GREAT tool to monitor PostgreSQL database dynamically. I would highly recommend this tool for DBAs for various reasons. This tool has numerous advantages, let me list them out:
    • pg_top tool uses textual interface and is similar to Unix “top” utility.
    • Will clearly list out the processes and the hardware resources utilized. What excites me with this tool is that it will clearly tell you if a particular process is currently on DISK or CPU - in my view that’s excellent. DBAs can clearly pick the process running for longer time on the disk.
    • You can check the EXPLAIN PLAN of the top SQLs dynamically or instantly
    • You can also find out what Tables or Indexes are being scanned instantly
  • Nagios is a popular monitoring tool for PostgreSQL which has both open-source and commercial versions. Open source version should suffice for monitoring. Custom Perl scripts can be built and plugged into Nagios module.
  • Pgbadger is a popular tool which can be used to analyze PostgreSQL log files and generate performance reports. This report can be used to analyze the performance of checkpoints, disk sorting.
  • Zabbix is another popular tool used for PostgreSQL monitoring.

ClusterControl is an up-and-coming management platform for PostgreSQL. Apart from monitoring, it also has functionality to deploy replication setups with load balancers, automatic failover, backup management, among others.