PostgreSQLLa base de données la plus sophistiquée au monde.

Version anglaise

pgbench

pgbench — lance un test de performance de PostgreSQL

Synopsis

pgbench -i [option...] [dbname]

pgbench [option...] [dbname]

Description

pgbench est un programme simple qui exécute un test de performances (benchmark en anglais) sur PostgreSQL™. Il exécute la même séquence de commandes SQL de nombreuses fois, si possible dans plusieurs sessions en parallèle, puis calcule le taux de transaction moyen (transactions par seconde). Par défaut, pgbench teste un scénario vaguement basé sur TPC-B, impliquant cinq SELECT, UPDATE et INSERT par transaction. Néanmoins il est facile de tester d'autres cas en écrivant ses propres fichiers de transaction.

Voici un exemple d'affichage de pgbench :

transaction type: TPC-B (sort of)
scaling factor: 10
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
tps = 85.184871 (including connections establishing)
tps = 85.296346 (excluding connections establishing)
   

Les six premières lignes indiquent simplement certains des paramètres les plus importants. La ligne suivant rapporte le nombre de transactions terminées et souhaitées (le dernier étant juste le produit du nombre de clients avec le nombre de transactions par client) ; ils doivent être égaux sauf si un échec est arrivé avant la fin (avec l'option -T, seul le nombre réel de transactions est affiché.) Les deux dernières lignes précisent le taux de transactions, avec et sans le temps de lancement de la session.

Le test de transaction par défaut, ressemblant à TPC-B, nécessite des tables particulières qu'il faut créer. pgbench doit être appelé avec l'option -i (initialisation) pour les créer et les peupler. (Cette étape n'est pas nécessaire dans le cas de script personnalisé, mais la base doit être configurée en conséquence.) L'initialisation ressemble à :

pgbench -i [ autres-options ] nom_base
   

nom_base est le nom d'une base de données déjà créée et à utiliser pour les tests. (Les options -h, -p, et/ou -U peuvent être utilisées pour indiquer la façon de se connecter au serveur de bases de données.)

[Attention]

Attention

pgbench -i crée quatre tables : pgbench_accounts, pgbench_branches, pgbench_history et pgbench_tellers, détruisant toute table existante de ce nom. Il convient d'y être attentif s'il existe des tables de même nom !

Avec un « facteur d'échelle » de 1, les tables contiennent initialement ce nombre de lignes :

table                   # de lignes
-----------------------------------
pgbench_branches        1
pgbench_tellers         10
pgbench_accounts        100000
pgbench_history         0
  

Le nombre de lignes peut être augmenté en utilisant l'option -s (facteur d'échelle). L'option -F (facteur de remplissage) peut aussi être utilisée à ce moment.

Une fois la configuration exécutée, le test de performance peut être lancé avec une commande qui n'inclut pas l'option -i, c'est-à-dire :

pgbench [ options ] nom_base
   

Dans la plupart des cas, vous aurez besoin de quelques options pour que ce test soit réellement intéressant. Les options les plus importantes sont -c (nombre de clients), -t (nombre de transactions), -T (limite de temps) et -f (pour spécifier un script personnalisé). Voir ci-dessous pour une liste complète.

Options

La documentation ci-après est répartie en trois sous-sections : des options différentes sont utilisées pour l'initialisation de la base de données, pour l'exécution des tests de performances, voire dans les deux cas.

Options d'initialisation

pgbench comprend les options de la ligne de commande suivants :

-i, --initialize

Requis lorsqu'on veut utiliser le mode d'initialisation.

-F facteur de remplissage, --fillfactor=facteur de remplissage

Crée les tables pgbench_accounts, pgbench_tellers et pgbench_branches avec le facteur de remplissage donné. La valeur par défaut est de 100.

-n, --no-vacuum

N'exécute aucun VACUUM après l'initialisation.

-q, --quiet

Bascule les traces en mode silencieux, ne faisant qu'un message de progression toutes les cinq secondes. Les traces par défaut impriment un message toutes les 100000 lignes, ce qui affiche souvent de nombreuses lignes par seconde, tout spécialement sur du bon matériel.

-r

Indique la latence moyenne par requête (temps d'exécution de la perspective du client) de chaque commande après la fin du test de performances. Voir ci-dessous pour les détails.

-s facteur d'echelle, --scale=facteur d'echelle

Multiplie le nombre de rangées par le facteur d'echelle. Par exemple, -s 100 créera 10,000,000 rangées dans la table pgbench_accounts. La valeur par défaut est de 1. Quand le facteur d'échelle est de 20000 ou plus, les colonnes utilisées pour les identifiants de compte (colonnes aid) basculeront vers le type bigint), pour qu'elles puissent contenir les identifiants en question.

--foreign-keys

Crée les clés étrangères entre les tables standards.

--index-tablespace=index_tablespace

Crée les index dans le tablespace spécifié, plutôt que dans le tablespace par défaut.

--tablespace=tablespace

Crée les tables dans le tablespace spécifié, plutôt que dans le tablespace par défaut.

--unlogged-tables

Crée toutes les tables comme des tables non journalisées, plutôt que comme des tables ordinaires.

Options de benchmark

pgbench comprend les options suivantes en ligne de commande :

-c clients, --client=clients

Nombre de clients simulés et donc le nombre de sessions concurrentes. La valeur par défaut est de 1.

-C, --connect

Établit une nouvelle connexion pour chaque transaction, plutôt que le faire une fois par session. Ceci est utile pour mésurer les ressources consommées par la connexion.

-d, --debug

Afficher la sortie de déboguage.

-D nom_variable=valeur, --define=nom_variable=valeur

Définit une variable pouvant être utilisé par un script personnalisé (voir plus bas). Plusieurs options -D peuvent être utilisées.

-f fichier, --file=fichier

Lire le script de transaction à partir de fichier. Voir plus bas pour les détails. -N, -S et -f ne peuvent pas être utilisés en même temps.

-j threads, --jobs=threads

Nombre de threads au sein de pgbench. L'utilisation de plus d'un thread peut être utile sur des machines multi-processeurs. Le nombre de client doit être un multiple du nombre de threads puisqu'on donne à chaque thread le même nombre de sessions clients à gérer. La valeur par défaut est de 1.

-l, --log

Écrire le temps pris par chaque transaction dans le fichier de log. Voir plus bas pour les détails.

-M mode de requête, --protocol=mode de requête

Protocole à utiliser pour soumettre les requêtes au serveur :

  • simple : utiliser le protocole de requêtes simples.

  • extended : utiliser le protocole de requêtes étendues.

  • prepared: utiliser le protocole de requêtes étendues avec instructions préparées.

Le protocole par defaut est celui de requêtes simples. (Voir Chapitre 49, Protocole client/serveur pour plus d'information.)

-n, --no-vacuum

Ne pas exécuter de VACUUM avant de lancer le test. Cette option est obligatoire si vous lancez un scénario de test personalisé qui n'inclut pas les tables standards pgbench_accounts, pgbench_branches, pgbench_history et pgbench_tellers.

-N, --skip-some-updates

Ne pas mettre à jour pgbench_tellers et pgbench_branches. Ceci évitera les problemes de mises à jour sur ces tables mais rendra les tests moins semblables à TPC-B.

-P sec, --progress=sec

Afficher la progression chaque sec secondes. Le rapport inclut le tmps depuis le début de l'exécution, le nombre de transactions par seconde depuis le dernier rapport, la latence moyenne des transactions, et la déviation standard depuis le dernier rapport. En utilisant l'option (-R), la latence est calculée en prenant en compte l'heure de début prévue de la transaction, et non pas l'heure de début réelle.. De ce faire, cela inclut aussi le temps de latence moyen.

-r, --report-latencies

Renvoie la latence moyenne par requête (durée d'exécution de la perspective du client) de chaque commande à la fin du benchmark. Voir ci-dessous pour les détails.

-R taux, --rate=taux

Exécuter les transactions en ciblant le taux indiqué plutôt que de les exécuter le plus rapidement possible (comportement par défaut). Le taux est donné en transactions par seconde. Si le taux cible est au-dessus du taux maximal, la limite de taux n'impactera pas les résultats.

Le taux est ciblé en commençant les transactions en utilisant une ligne de temps basée sur la distribution de Poisson. Le temps de démarrage attendu se déplace suivant le premier client démarré, et non pas suivant la fin de la transaction précédente. Cette approche signifie que, quand les transactions dépassent leur durée finale prévue, les suivants peuvent récupérer de nouveau.

Lorsque la limitation est activée, la latence des transactions rapportée en fin de test est calculée à partir de l'heure de début prévue, de sorte qu'il comprend le temps d'attente de la fin de la transaction précédente. La durée d'attente est appelée durée de latence planifiée, et ses valeur moyenne et valeur maximale sont aussi rapportées séparément. La latence de la transaction, calculée partir de l'heure de début réelle de la transactions, donc le temps passé à exécuter la transaction au niveau de la base de données, peut se calculer en soustrayant la durée de la latence planifiée de la latence rapportée.

Une grande durée de latence planifiée est une indication que le système ne peut pas traiter les transactions à ce rythme, avec le nombre choisi de clients et de threads. Quand la durée d'exécution moyenne des transactions est plus longue que l'intervalle planifié entre chaque transactions, toutes les transactions suivantes vont durer encore plus longtemps, et la durée de latence planifiée ne fera que grossir jusqu'à la fin de l'exécution du test. Quand ceci survient, vous devez réduire le taux de transaction indiqué.

-s facteur d'échelle, --scale=facteur d'échelle

Rapporter le facteur d'echelle spécifié dans la sortie de pgbench. Avec les tests intégrés par défaut, ceci n'est pas necessaie ; le facteur sera déduit en comptant les nombres de rangées dans la table pgbench_branches. Par contre, lors que vous testerez des benchmarks personalisés (avec l'option -f), le facteur rapporté sera de 1 sauf si cette option est utilisée.

-S, --select-only

Faire des tests à base de select uniquement plutôt que TPC-B.

-t transactions, --transactions=transactions

Le nombre de transactions que chaque client doit jouer. Le défaut est de 10.

-T secondes, --time=secondes

Lancer ce test autant de secondes, plutôt qu'un nombre fixe de transactions par clients. -t et -T ne peuvent pas être utilisés en même temps.

-v, --vacuum-all

Faire un vacuum sur les quatre tables standard avant de lancer le test. Sans -n ou -v, pgbench fera un vacuum sur les tables pgbench_tellers et pgbench_branches et tronquera pgbench_history.

--aggregate-interval seconds

Longueur de l'intervalle d'agrégation (en secondes). Peut seulement être utilisée avec -l - avec cette option, la trace contient un résumé par intervalle (nombre de transactions, latence minimale et maximale, et deux champs supplémentaires utiles pour l'estimation de la variance).

Cette option n'est actuellement pas supportée sous Windows.

--sampling-rate taux

Taux d'échantillonnage, utilisé lors de l'écriture des données dans les traces, pour réduire la quantité de traces générées. Si cette option est fournie, seule la fraction de transactions indiquées est tracée. 1,0 signifie que toutes les transactions seront tracées, 0,05 signifie que seulement 5% des transactions seront tracées.

Rappelez-vous de prendre en compte le taux d'échantillonnage lors du traitement du fichier de traces. Par exemple, lors du calcul du nombre de transactions par seconde, vous aurez besoin de multiplier les nombres en concordance (par exemple avec un taux d'échantillonnage de 0,01, vous obtiendrez réellement un centième du nombre de transactions par seconde).

Options générales

pgbench reconnait les options habituelles suivantes de ligne de commande :

-h nom de machine, --host=nom de machine

Le nom de machine du serveur base de données

-p port, --port=port

Le numéro de port du serveur base de données

-U nom d'utilisateur, --username=nom d'utilisateur

Le nom avec lequel se connecter

-V, --version

Affiche la version de pgbench, puis quitte.

-?, --help

Affiche l'aide sur les arguments en ligne de commande pgbench, puis quitte.

Notes

Quelle « transaction » est réalisée dans pgbench ?

Le script de transaction par défaut exécute sept commandes :

  1. BEGIN;

  2. UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;

  3. SELECT abalance FROM pgbench_accounts WHERE aid = :aid;

  4. UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;

  5. UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;

  6. INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);

  7. END;

Si vous indiquez -N, les étapes 4 et 5 ne sont pas inclus dans la transaction. Si vous indiquez -S, seul le SELECT est exécuté.

Scripts personnalisés

pgbench sait exécuter des scénarios personnalisés en remplaçant le script de transaction par défaut (décrit ci-dessus) avec un script de transaction lu à partir d'un fichier (option -f). Dans ce cas, une « transaction » compte en tant qu'une exécution du fichier. Vous pouvez même indiquer plusieurs scripts (avec plusieurs options -f), auquel cas un script est choisi au hasard à chaque fois qu'une session client exécute une nouvelle transaction.

Le fichier doit contenir une commande par ligne ; les commandes SQL multi-lignes ne sont pas acceptées. Les lignes vides et les lignes commençant par -- sont ignorées. Les lignes du fichier peuvent aussi contenir des « meta commandes », qui sont interprétées par pgbench lui-même, comme décrit ci-dessous.

Il existe une fonctionnalité de substitution de variables pour les fichiers. Les variables sont configurables par l'option -D en ligne de commande, comme expliqué ci-dessus, ou par les méta-commandes expliquées ci-dessous. En plus des variables pré-initialisées par les options -D, il existe quelques variables préconfigurées automatiquement, listées dans Tableau G.1, « Variables automatiques ». Une valeur indiquée pour ces variables en utilisant l'option -D prénd précédence sur les préconfigurations automatiques. Une fois configurée, la valeur d'une variable peut être insérée dans une commande SQL en écrivant :nom_variable. Lors de l'exécution de plusieurs sessions clients, chaque session a son propre ensemble de variables.

Tableau G.1. Variables automatiques

Variable Description
scale facteur d'échelle actuel
client_id numéro unique identifiant la session du client (commence à partir de zéro)

Les méta-commandes du script commencent par un antislash (\). Les arguments d'une méta-commande sont séparés par des espaces blancs. Voici la liste des méta-commandes acceptées :

\set nom_variable operande1 [ operateur operande2 ]

Initialise la variable varname avec une valeur entière calculée. Chaque operande est soit une constante entière soit une référence :nom_variable à une variable entière. L'operateur peut être +, -, * ou /.

Exemple :

\set ntellers 10 * :scale
       
\setrandom nom_variable min max

Initialise la variable nom_variable à une valeur entière prise au hasard entre les limites min et max, limites inclues. Chaque limite peut être soit une constante entière soit une référence :nom_variable à une valeur entière.

Exemple :

\setrandom aid 1 :naccounts
       
\sleep nombre [ us | ms | s ]

Provoque un endormissement de l'exécution du script pour la durée indiquée en microsecondes (us), millisecondes (ms) ou secondes (s). Si l'unité est omise, alors ce seront par défaut des secondes. nombre peut être soit un entier soit une référence :nom_variable à un entier.

Exemple :

\sleep 10 ms
       
\setshell nom_variable commande [ argument ... ]

Configure la variable nom_variable avec le résultat de la commande shell commande. La commande doit renvoyer une valeur entière via sa sortie standard.

argument peut être soit une constante de type texte soit une référence :nom_variable à une variable de n'importe quel type. Si vous voulez utiliser argument en commençant avec un signe deux-points, vous devez ajouer un signe deux-points supplémentaires au début de argument.

Exemple :

\setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon
       
\shell commande [ argument ... ]

Idem à \setshell, mais le résultat est ignoré.

Exemple :

\shell command literal_argument :variable ::literal_starting_with_colon
       

En exemple, voici la définition complète d'une transaction style TPC-B :

\set nbranches :scale
\set ntellers 10 * :scale
\set naccounts 100000 * :scale
\setrandom aid 1 :naccounts
\setrandom bid 1 :nbranches
\setrandom tid 1 :ntellers
\setrandom delta -5000 5000
BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;
    

Ce script permet à chaque itération de la transaction de référencer des lignes différentes, prises au hasard. (Cet exemple montre aussi pourquoi il est imporant que chaque session client ait ses propres variables -- sinon elles ne traiteraient pas des lignes différentes.)

Journalisation par transaction

Avec l'option -l mais sans l'option --aggregate-interval, pgbench écrit la durée prise par chaque transaction dans un fichier de traces. Le journal sera nommé pgbench_log.nnn, où nnn est le PID du processus pgbench. Si l'option -j vaut 2 ou plus, ce qui va créer plusieurs threads de travail, chacun d'entre eux aura son propre journal applicatif. Le premier utilise le même nom de fichier que s'il avait été seul. Les autres fichiers des autres travailleurs seront nommés pgbench_log.nnn.mmm, où mmm est un numéro séquentiel pour chaque travailleur et commençant à 1.

Le format de ce journal est :

    client_id transaction_no time file_no time_epoch time_us [schedule_lag]
    

time est la durée totale de la transaction en microsecondes, file_no identifie le script qui a été utilisé (utile quand plusieurs scripts sont indiqués avec -f) et time_epoch/time_us sont une date/heure au format epoch Unix et un décalage en microsecondes (convenable pour la création d'un horodatage ISO 8601 avec des secondes en fraction) indiquant la date et heure de la fin de la transaction. Le dernier champ, schedule_lag, est la différence entre l'heure de début planifiée de la transaction, et l'heure à laquelle elle a réellement commencé, en microsecondes. Cette information n'est présente que si l'option --rate est utilisée.

Voici un exemple de journal :

 0 199 2241 0 1175850568 995598
 0 200 2465 0 1175850568 998079
 0 201 2513 0 1175850569 608
 0 202 2038 0 1175850569 2663
    

Lors de l'exécution d'un test long sur du matériel qui peut gérer un grand nombre de transactions, les traces peuvent devenir très grosses. L'option --sampling-rate peut être utilisée pour ne tracer qu'un ensemble aléatoire de transactions.

Traces agrégées

Avec l'option --aggregate-interval, les traces utilisent un format un peu différent :

début_intervalle nombre_de_transactions somme_latence somme_latence_2 min_latence max_latence [lag_sum lag_2_sum min_lag max_lag]
    

début_intervalle est le début de l'intervalle (horodatage au format UNIX epoch), nombre_de_transactions est le nombre de transactions dans cet intervalle, somme_latence est la somme des latences (pour que vous puissiez calculer la moyenne facilement). Les deux champs suivants sont utiles pour estimer la variances - somme_latence est une somme des latences et somme_latence_2 est une somme des latence puissance 2. Les deux derniers champs sont min_latence - la latence minimale dans cet intervalle, et max_latence - la latence maximale dans cet intervalle. Une transaction est comptée dans l'intervalle où elle a été validée. Les quatre derniers champs, lag_sum, lag_2_sum, min_lag et max_lag, sont seulement présents si l'option est utilisée. Ils sont calculés à partir du moment où chaque transaction doit attendre la fin de la précédente, autrement dit la différence entre l'heure de début planifiée de chaque transaction et l'heure de début réelle.

Voici un exemple de sortie :

1345828501 5601 1542744 483552416 61 2573
1345828503 7884 1979812 565806736 60 1479
1345828505 7208 1979422 567277552 59 1391
1345828507 7685 1980268 569784714 60 1398
1345828509 7073 1979779 573489941 236 1411
    

Notez que, bien que la trace simple (non agrégée) contient une référence des fichiers de script personnalisés, la trace agrégée n'en contient pas. Du coup, si vous avez besoin de données par script, vous devez agréger les données vous-même.

Latence par requête

Avec l'option -r, pgbench récupère le temps passé sur chaque requête exécutée par les clients. Il affiche ensuite la moyenne de ces valeurs, comme la latence de chaque requête, une fois que le test de performances est terminé.

Pour le script par défaut, la sortie ressemble à ceci :

starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
tps = 618.764555 (including connections establishing)
tps = 622.977698 (excluding connections establishing)
statement latencies in milliseconds:
        0.004386        \set nbranches 1 * :scale
        0.001343        \set ntellers 10 * :scale
        0.001212        \set naccounts 100000 * :scale
        0.001310        \setrandom aid 1 :naccounts
        0.001073        \setrandom bid 1 :nbranches
        0.001005        \setrandom tid 1 :ntellers
        0.001078        \setrandom delta -5000 5000
        0.326152        BEGIN;
        0.603376        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
        0.454643        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
        5.528491        UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
        7.335435        UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
        0.371851        INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
        1.212976        END;
    

Si plusieurs fichiers de script sont donnés, les moyennes sont reportées séparément pour chaque fichier de script.

Notez que la récupération de cette information pour chaque requête exécutée ajoute une surcharge. Cela ralentira la vitesse d'exécution moyenne et diminuera d'autant le nombre de transactions par seconde calculé. Le ralentissement constaté varie significativement suivant la plateforme et le matériel. Comparer les valeurs moyennes avec et sans latence est une bonne façon de constater si la surcharge est significative ou non.

Bonnes pratiques

Il est très facile d'utiliser pgbench pour produire des nombres sans signification. Voici quelques lignes de conduite pour vous aider à obtenir des résultats intéressants.

En premier lieu, ne jamais croire tout test qui ne s'exécute que pendant quelques secondes. Utilisez l'option -t ou -T pour que le test dure plusieurs minutes pour rendre le bruit insignifiant. Dans certains cas, nous avez besoin de quelques heures pour obtenir des chiffres reproductibles. Exécuter le test plusieurs fois est une bonne idée pour savoir si vos résultats sont reproductibles.

Pour le scénario par défaut, style TPC-B, le facteur d'échelle à l'initialisation (-s) doit être au moins aussi important que le plus grand nombre de clients que vous souhaitez supporter (-c) ; sinon vous ne ferez que mesurer la contention des mises à jour. Il n'y a que -s lignes dans la table pgbench_branches, et chaque transaction veut en mettre une à jour, donc les valeurs -c supérieures à -s résulteront sans doute en beaucoup de transactions bloquées, en attente d'autres transactions.

Le scénario test par défaut est aussi assez sensible du moment où les tables ont été initialisées : une accumulation de lignes morts et d'espace vide dans les tables modifient les résultats. Pour comprendre les résultats, vous devez garder trace de nombre total de mises à jour et des moments où un VACUUM est exécuté. Si l'autovacuum est activé, cela peut causer des modifications non prévisibles dans les performances mesurées.

Une limite de pgbench est qu'il peut devenir lui-même le goulot d'étranglement lors de tentative de tests d'un grand nombre de sessions clients. Ceci peut se voir allégé en exécutant pgbench sur une autre machine que le serveur de bases de données, bien que la latence du réseau est essentielle. Il pourrait même être utile d'exécuter plusieurs instances pgbench en parallèle sur plusieurs machines client, pour le même serveur de bases de données.