Nous avons commencé par des problèmes liés à l'
isolement , avons fait une digression sur l'
organisation des données à un bas niveau , puis avons parlé en détail des
versions de ligne et de la façon dont les
instantanés sont obtenus à partir des versions.
La dernière fois, nous avons parlé des mises à jour HOT et du nettoyage sur la page, et aujourd'hui nous allons jeter un œil au célèbre nettoyage ordinaire, l'
aspirateur vulgaris . Oui, tant de choses ont déjà été écrites à son sujet qu'il est peu probable que je dise quelque chose de nouveau, mais l'exhaustivité de l'image nécessite un sacrifice. Soyez patient.
Nettoyage normal (aspirateur)
Que fait le nettoyage
Le nettoyage intra-page est rapide, mais ne libère qu'une fraction de l'espace. Il fonctionne dans la même page tabulaire et n'affecte pas les index.
Le nettoyage principal «normal» est effectué par la commande VACUUM et nous l'appellerons simplement nettoyage (et nous parlerons de l'autonettoyage séparément).
Ainsi, le nettoyage traite complètement la table. Il nettoie non seulement les versions inutiles des chaînes, mais également les références à celles-ci de tous les index.
Le traitement se déroule en parallèle avec d'autres activités du système. Dans ce cas, la table et les index peuvent être utilisés de la manière habituelle à la fois pour la lecture et pour la modification (cependant, l'exécution simultanée de commandes telles que CREATE INDEX, ALTER TABLE et quelques autres sera impossible).
Seules les pages dans lesquelles une certaine activité s'est produite sont affichées dans le tableau. Pour cela, une carte de visibilité est utilisée (je vous rappelle que les pages contenant uniquement des versions de lignes assez anciennes qui sont garanties d'être visibles dans tous les instantanés de données y sont marquées). Seules les pages non marquées sur la carte sont traitées, tandis que la carte elle-même est mise à jour.
Dans le processus, la carte d'espace libre est mise à jour pour refléter l'espace libre qui apparaît dans les pages.
Comme d'habitude, créez un tableau:
=> CREATE TABLE vac( id serial, s char(100) ) WITH (autovacuum_enabled = off); => CREATE INDEX vac_s ON vac(s); => INSERT INTO vac(s) VALUES ('A'); => UPDATE vac SET s = 'B'; => UPDATE vac SET s = 'C';
En utilisant le paramètre
autovacuum_enabled, nous désactivons le nettoyage automatique. Nous en reparlerons la prochaine fois, mais pour l'instant - pour les expérimentations - il est important pour nous de gérer le nettoyage manuellement.
Il existe maintenant trois versions de la ligne dans le tableau, et chacune est liée à partir d'un index:
=> SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+----------+-----+-----+-------- (0,1) | normal | 4000 (c) | 4001 (c) | | | (0,2) (0,2) | normal | 4001 (c) | 4002 | | | (0,3) (0,3) | normal | 4002 | 0 (a) | | | (0,3) (3 rows)
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,1) 2 | (0,2) 3 | (0,3) (3 rows)
Après le nettoyage, les versions "mortes" disparaissent et il n'y en a qu'une, pertinente. Et l'index a également un lien à gauche:
=> VACUUM vac; => SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+-------+-----+-----+-------- (0,1) | unused | | | | | (0,2) | unused | | | | | (0,3) | normal | 4002 (c) | 0 (a) | | | (0,3) (3 rows)
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,3) (1 row)
Veuillez noter que les deux premiers pointeurs ont reçu le statut inutilisé et non mort, comme ce serait le cas avec le nettoyage intra-page.
Et encore une fois sur l'horizon des transactions
Comment PostgreSQL détermine-t-il quelles versions de lignes peuvent être considérées comme «mortes»? Nous avons déjà envisagé le concept d'un horizon de transaction lorsque nous avons parlé
d' instantanés de
données , mais c'est un sujet tellement important que ce n'est pas un péché de le répéter.
Reprenons l'expérience précédente.
=> TRUNCATE vac; => INSERT INTO vac(s) VALUES ('A'); => UPDATE vac SET s = 'B';
Mais avant de mettre à jour la ligne à nouveau, laissez une autre transaction commencer (mais pas se terminer). Dans notre exemple, cela fonctionnera au niveau de lecture validée, mais devrait obtenir un vrai numéro de transaction (non virtuel). Par exemple, il peut changer ou même simplement verrouiller certaines lignes dans n'importe quelle table, pas nécessairement dans vac:
| => BEGIN; | => SELECT s FROM t FOR UPDATE;
| s | ----- | FOO | BAR | (2 rows)
=> UPDATE vac SET s = 'C';
Il y a trois lignes dans le tableau et trois liens dans l'index. Que se passe-t-il après le nettoyage?
=> VACUUM vac; => SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+----------+-----+-----+-------- (0,1) | unused | | | | | (0,2) | normal | 4005 (c) | 4007 (c) | | | (0,3) (0,3) | normal | 4007 (c) | 0 (a) | | | (0,3) (3 rows)
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,2) 2 | (0,3) (2 rows)
Il reste deux versions de la ligne dans le tableau: le nettoyage a décidé que la version (0.2) ne pouvait pas encore être supprimée. La raison, bien sûr, est dans l'horizon des transactions de la base de données, qui dans notre exemple est déterminé par une transaction incomplète:
| => SELECT backend_xmin FROM pg_stat_activity WHERE pid = pg_backend_pid();
| backend_xmin | -------------- | 4006 | (1 row)
Vous pouvez demander un nettoyage pour parler de ce qui se passe:
=> VACUUM VERBOSE vac;
INFO: vacuuming "public.vac" INFO: index "vac_s" now contains 2 row versions in 2 pages DETAIL: 0 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "vac": found 0 removable, 2 nonremovable row versions in 1 out of 1 pages DETAIL: 1 dead row versions cannot be removed yet, oldest xmin: 4006 There were 1 unused item pointers. Skipped 0 pages due to buffer pins, 0 frozen pages. 0 pages are entirely empty. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. VACUUM
Veuillez noter:
- 2 versions de ligne non amovibles - 2 versions ont été trouvées dans le tableau qui ne peuvent pas être supprimées,
- 1 versions de ligne morte ne peuvent pas encore être supprimées - dont 1 «mort»,
- le xmin le plus ancien montre l'horizon actuel.
Nous répétons une fois de plus la conclusion: la présence de transactions de longue durée dans la base de données (non terminées ou très longues) peut conduire à l'expansion des tables (gonflées), quelle que soit la fréquence du nettoyage. Par conséquent, dans PostgreSQL, les charges de travail OLTP et OLAP sont mal combinées dans une seule base de données: les rapports qui s'exécutent pendant des heures ne permettront pas d'effacer les tables fréquemment mises à jour à temps. Une solution possible serait de créer une réplique de «rapport» distincte.
Après l'achèvement d'une transaction ouverte, l'horizon change et la situation est corrigée:
| => COMMIT;
=> VACUUM VERBOSE vac;
INFO: vacuuming "public.vac" INFO: scanned index "vac_s" to remove 1 row versions DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: "vac": removed 1 row versions in 1 pages DETAIL: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s INFO: index "vac_s" now contains 1 row versions in 2 pages DETAIL: 1 index row versions were removed. 0 index pages have been deleted, 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "vac": found 1 removable, 1 nonremovable row versions in 1 out of 1 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4008 There were 1 unused item pointers. Skipped 0 pages due to buffer pins, 0 frozen pages. 0 pages are entirely empty. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. VACUUM
Maintenant, la page n'a que la dernière version actuelle de la ligne:
=> SELECT * FROM heap_page('vac',0);
ctid | state | xmin | xmax | hhu | hot | t_ctid -------+--------+----------+-------+-----+-----+-------- (0,1) | unused | | | | | (0,2) | unused | | | | | (0,3) | normal | 4007 (c) | 0 (a) | | | (0,3) (3 rows)
Il n'y a également qu'une seule entrée dans l'index:
=> SELECT * FROM index_page('vac_s',1);
itemoffset | ctid ------------+------- 1 | (0,3) (1 row)
Que se passe-t-il à l'intérieur
Le nettoyage doit traiter à la fois la table et les index en même temps et de manière à ne pas bloquer le fonctionnement des autres processus. Comment fait-elle?
Tout commence par
un scan de table (en tenant compte de la carte de visibilité, comme déjà indiqué). Dans les pages lues, les versions inutiles des chaînes sont déterminées et leurs identificateurs (tid) sont écrits dans un tableau spécial. La baie est située dans la mémoire locale du processus de nettoyage; un fragment de taille
maintenance_work_mem lui est alloué. La valeur par défaut de ce paramètre est 64 Mo. Notez que cette mémoire est allouée immédiatement dans son intégralité, et pas au besoin. Vrai, si la table est petite, alors le fragment est alloué moins.
Ensuite, l'une des deux choses: soit nous atteindrons la fin de la table, soit la mémoire allouée au tableau se terminera. Dans l'un ou l'autre des deux cas,
la phase de nettoyage d'index commence. Pour ce faire,
chacun des index créés sur la table est
entièrement analysé à la recherche d'enregistrements faisant référence aux versions stockées des lignes. Les enregistrements trouvés sont effacés des pages d'index.
À ce stade, nous obtenons l'image suivante: dans les index, il n'y a plus de liens vers des versions inutiles de lignes, mais ils existent toujours dans la table. Cela ne contredit rien: lors de l'exécution d'une requête, soit nous n'atteignons pas du tout les versions mortes des lignes (avec accès à l'index), soit nous les marquons lors de la vérification de la visibilité (lors de l'analyse d'une table).
Après cela,
la phase de nettoyage de la table commence. Le tableau est à nouveau analysé pour lire les pages nécessaires, pour en supprimer les versions stockées des lignes et pour libérer les pointeurs. Nous pouvons le faire car il n'y a plus de liens à partir des index.
Si le tableau n'a pas été complètement lu lors de la première passe, le tableau est effacé et tout est répété depuis l'endroit où nous nous sommes arrêtés.
De cette façon:
- la table est toujours scannée deux fois;
- si tant de versions de lignes sont supprimées lors du nettoyage que toutes ne peuvent pas tenir dans la mémoire maintenance_work_mem , tous les index seront analysés complètement autant de fois que nécessaire.
Sur les grandes tables, cela peut prendre un temps considérable et créer une charge importante sur le système. Bien sûr, les demandes ne seront pas bloquées, mais les E / S "supplémentaires" sont également désagréables.
Pour accélérer le processus, il est judicieux soit d'appeler au nettoyage plus souvent (afin que pas un très grand nombre de versions de lignes soient effacées à chaque fois), soit d'allouer plus de mémoire.
Je note entre parenthèses qu'à partir de la version 11, PostgreSQL
peut ignorer les analyses d'index si ce n'est pas absolument nécessaire. Cela devrait faciliter la vie des propriétaires de grandes tables dans lesquelles des lignes sont uniquement ajoutées (mais pas modifiées).
Suivi
Comment comprendre que le nettoyage ne résiste pas au travail en un seul passage?
Nous avons déjà vu la première méthode: vous pouvez appeler la commande VACUUM avec VERBOSE. Ensuite, des informations sur les phases du travail seront affichées sur la console.
Deuxièmement, à partir de la version 9.6, il y a une vue pg_stat_progress_vacuum, qui contient également toutes les informations nécessaires.
(Il existe une troisième méthode - pour afficher des informations dans le journal des messages, mais cela ne fonctionne que pour le nettoyage automatique, qui sera discuté la prochaine fois.)
Nous allons insérer plus de lignes dans le tableau afin que le nettoyage prenne un temps considérable, et nous les mettrons à jour afin qu'il y ait quelque chose à voir avec le nettoyage.
=> TRUNCATE vac; => INSERT INTO vac(s) SELECT 'A' FROM generate_series(1,500000); => UPDATE vac SET s = 'B';
Réduisez la taille de la mémoire allouée au tableau d'identificateurs:
=> ALTER SYSTEM SET maintenance_work_mem = '1MB'; => SELECT pg_reload_conf();
Nous commençons le nettoyage et, pendant que cela fonctionne, nous allons passer plusieurs fois à la vue pg_stat_progress_vacuum:
=> VACUUM VERBOSE vac;
| => SELECT * FROM pg_stat_progress_vacuum \gx
| -[ RECORD 1 ]------+------------------ | pid | 6715 | datid | 41493 | datname | test | relid | 57383 | phase | vacuuming indexes | heap_blks_total | 16667 | heap_blks_scanned | 2908 | heap_blks_vacuumed | 0 | index_vacuum_count | 0 | max_dead_tuples | 174762 | num_dead_tuples | 174480
| => SELECT * FROM pg_stat_progress_vacuum \gx
| -[ RECORD 1 ]------+------------------ | pid | 6715 | datid | 41493 | datname | test | relid | 57383 | phase | vacuuming indexes | heap_blks_total | 16667 | heap_blks_scanned | 5816 | heap_blks_vacuumed | 2907 | index_vacuum_count | 1 | max_dead_tuples | 174762 | num_dead_tuples | 174480
Ici, nous voyons en particulier:
- nom de la phase actuelle (phase) - nous avons parlé de trois phases principales, mais en général il y en a plus ;
- nombre total de pages de table (heap_blks_total);
- le nombre de pages analysées (heap_blks_scanned);
- le nombre de pages déjà effacées (heap_blks_vacuumed);
- le nombre de passes par index (index_vacuum_count).
La progression globale est déterminée par le rapport de heap_blks_vacuumed à heap_blks_total, mais gardez à l'esprit que cette valeur ne change pas en douceur, mais «saccadée» en raison des analyses d'index. Cependant, l'attention principale doit être accordée au nombre de cycles de nettoyage - une valeur supérieure à 1 signifie que la mémoire allouée n'était pas suffisante pour terminer le nettoyage en une seule passe.
La sortie de la commande VACUUM VERBOSE, terminée à ce moment, affichera la vue d'ensemble:
INFO: vacuuming "public.vac"
INFO: scanned index "vac_s" to remove 174480 row versions DETAIL: CPU: user: 0.50 s, system: 0.07 s, elapsed: 1.36 s INFO: "vac": removed 174480 row versions in 2908 pages DETAIL: CPU: user: 0.02 s, system: 0.02 s, elapsed: 0.13 s
INFO: scanned index "vac_s" to remove 174480 row versions DETAIL: CPU: user: 0.26 s, system: 0.07 s, elapsed: 0.81 s INFO: "vac": removed 174480 row versions in 2908 pages DETAIL: CPU: user: 0.01 s, system: 0.02 s, elapsed: 0.10 s
INFO: scanned index "vac_s" to remove 151040 row versions DETAIL: CPU: user: 0.13 s, system: 0.04 s, elapsed: 0.47 s INFO: "vac": removed 151040 row versions in 2518 pages DETAIL: CPU: user: 0.01 s, system: 0.02 s, elapsed: 0.08 s
INFO: index "vac_s" now contains 500000 row versions in 17821 pages DETAIL: 500000 index row versions were removed. 8778 index pages have been deleted, 0 are currently reusable. CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s. INFO: "vac": found 500000 removable, 500000 nonremovable row versions in 16667 out of 16667 pages DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4011 There were 0 unused item pointers. 0 pages are entirely empty. CPU: user: 1.10 s, system: 0.37 s, elapsed: 3.71 s. VACUUM
Ici, vous pouvez voir qu'au total, il y a eu trois passages dans les indices, chacun ayant effacé 174 480 pointeurs vers des versions mortes de chaînes. D'où vient ce chiffre? Un lien (tid) prend 6 octets, et 1024 * 1024/6 = 174762 est le nombre que nous voyons dans pg_stat_progress_vacuum.max_dead_tuples. En fait, il peut être utilisé un peu moins: il est garanti qu'à la lecture de la page suivante, tous les pointeurs vers les versions "mortes" tiendront exactement en mémoire.
Analyse
L'analyse, ou, en d'autres termes, la collecte d'informations statistiques pour le planificateur de requêtes, n'est pas formellement liée au nettoyage. Néanmoins, nous pouvons effectuer l'analyse non seulement avec l'équipe ANALYZE, mais également combiner le nettoyage avec l'analyse: VACUUM ANALYZE. Dans ce cas, le nettoyage est d'abord effectué, puis l'analyse - aucune économie ne se produit.
Mais, comme nous le verrons plus loin, le nettoyage automatique et l'analyse automatique sont effectués en un seul processus et sont gérés de manière similaire.
Nettoyage complet (vide plein)
Comme nous l'avons vu, le nettoyage conventionnel libère plus d'espace que le nettoyage intra-page, mais même cela ne résout pas toujours complètement le problème.
Si, pour une raison quelconque, la taille de la table ou de l'index a considérablement augmenté, un nettoyage régulier libérera de l'espace à l'intérieur des pages existantes: ils contiendront des «trous», qui seront ensuite utilisés pour insérer de nouvelles versions de lignes. Mais le nombre de pages ne changera pas et, par conséquent, du point de vue du système d'exploitation, les fichiers occuperont exactement la même quantité d'espace qu'ils occupaient avant le nettoyage. Et c'est mauvais parce que:
- l'analyse complète d'une table (ou d'un index) ralentit;
- un cache tampon plus important peut être nécessaire (car les pages sont stockées et la densité des informations utiles diminue);
- un niveau «supplémentaire» peut apparaître dans l'arborescence d'index, ce qui ralentira l'accès à l'index;
- les fichiers prennent de l'espace disque supplémentaire et des sauvegardes.
(La seule exception est les pages complètement nettoyées à la fin du fichier - ces pages «mordent» le fichier et reviennent au système d'exploitation.)
Si la part des informations utiles dans les fichiers tombe en dessous d'une limite raisonnable, l'administrateur peut effectuer un nettoyage complet de la table. Dans le même temps, la table et tous ses index sont entièrement reconstruits à partir de zéro, et les données sont compressées aussi compactement que possible (bien sûr, en tenant compte du paramètre fillfactor). Lors de la reconstruction, PostgreSQL reconstruit séquentiellement la table d'abord, puis chacun de ses index. De nouveaux fichiers sont créés pour chaque objet et à la fin de la reconstruction, les anciens fichiers sont supprimés. Veuillez noter que dans le processus de travail sur le disque, il faudra de l'espace supplémentaire.
Pour illustrer, insérez à nouveau un certain nombre de lignes dans le tableau:
=> TRUNCATE vac; => INSERT INTO vac(s) SELECT 'A' FROM generate_series(1,500000);
Comment évaluer la densité de l'information? Pour ce faire, il est pratique d'utiliser l'extension spéciale:
=> CREATE EXTENSION pgstattuple; => SELECT * FROM pgstattuple('vac') \gx
-[ RECORD 1 ]------+--------- table_len | 68272128 tuple_count | 500000 tuple_len | 64500000 tuple_percent | 94.47 dead_tuple_count | 0 dead_tuple_len | 0 dead_tuple_percent | 0 free_space | 38776 free_percent | 0.06
La fonction lit l'ensemble du tableau et affiche des statistiques sur la quantité d'espace quelles données sont occupées dans les fichiers. La principale information qui nous intéresse maintenant est le champ tuple_percent: le pourcentage occupé par les données utiles. Il est inférieur à 100 en raison de la surcharge inévitable d'informations de service à l'intérieur de la page, mais néanmoins assez élevé.
Pour l'index, d'autres informations sont affichées, mais le champ avg_leaf_density a la même signification: le pourcentage d'informations utiles (en pages feuilles).
=> SELECT * FROM pgstatindex('vac_s') \gx
-[ RECORD 1 ]------+--------- version | 3 tree_level | 3 index_size | 72802304 root_block_no | 2722 internal_pages | 241 leaf_pages | 8645 empty_pages | 0 deleted_pages | 0 avg_leaf_density | 83.77 leaf_fragmentation | 64.25
Et voici la taille de la table et de l'index:
=> SELECT pg_size_pretty(pg_table_size('vac')) table_size, pg_size_pretty(pg_indexes_size('vac')) index_size;
table_size | index_size ------------+------------ 65 MB | 69 MB (1 row)
Supprimez maintenant 90% de toutes les lignes. Nous sélectionnons les lignes à supprimer de manière aléatoire, de sorte que dans chaque page avec une probabilité élevée, au moins une ligne reste:
=> DELETE FROM vac WHERE random() < 0.9;
DELETE 450189
Quelle taille auront les objets après un nettoyage normal?
=> VACUUM vac; => SELECT pg_size_pretty(pg_table_size('vac')) table_size, pg_size_pretty(pg_indexes_size('vac')) index_size;
table_size | index_size ------------+------------ 65 MB | 69 MB (1 row)
Nous constatons que la taille n'a pas changé: un nettoyage régulier ne peut en aucun cas réduire la taille des fichiers. Bien que la densité de l'information ait évidemment diminué d'environ 10 fois:
=> SELECT vac.tuple_percent, vac_s.avg_leaf_density FROM pgstattuple('vac') vac, pgstatindex('vac_s') vac_s;
tuple_percent | avg_leaf_density ---------------+------------------ 9.41 | 9.73 (1 row)
Vérifiez maintenant ce qui se passe après un nettoyage complet. Voici les fichiers utilisés par la table et les index maintenant:
=> SELECT pg_relation_filepath('vac'), pg_relation_filepath('vac_s');
pg_relation_filepath | pg_relation_filepath ----------------------+---------------------- base/41493/57392 | base/41493/57393 (1 row)
=> VACUUM FULL vac; => SELECT pg_relation_filepath('vac'), pg_relation_filepath('vac_s');
pg_relation_filepath | pg_relation_filepath ----------------------+---------------------- base/41493/57404 | base/41493/57407 (1 row)
Maintenant, les fichiers sont remplacés par de nouveaux. La taille du tableau et de l'index a considérablement diminué et la densité des informations a donc augmenté:
=> SELECT pg_size_pretty(pg_table_size('vac')) table_size, pg_size_pretty(pg_indexes_size('vac')) index_size;
table_size | index_size ------------+------------ 6648 kB | 6480 kB (1 row)
=> SELECT vac.tuple_percent, vac_s.avg_leaf_density FROM pgstattuple('vac') vac, pgstatindex('vac_s') vac_s;
tuple_percent | avg_leaf_density ---------------+------------------ 94.39 | 91.08 (1 row)
Veuillez noter que la densité des informations dans l'index a même augmenté par rapport à l'original. La recréation d'un index (arbre B) à partir des données disponibles est plus rentable que l'insertion de données dans un index existant ligne par ligne.
Les fonctions d'extension
pgstattuple que nous avons utilisées lisent l'intégralité du tableau. Si le tableau est grand, cela n'est pas pratique, et il y a donc une fonction pgstattuple_approx, qui saute les pages marquées dans la carte de visibilité et affiche des nombres approximatifs.
Une méthode encore plus rapide, mais encore moins précise, consiste à estimer le rapport entre le volume de données et la taille du fichier dans le répertoire système. Les options pour de telles requêtes peuvent être trouvées
sur le wiki .
Un nettoyage complet ne nécessite pas d'utilisation régulière, car il bloque complètement tout travail avec la table (y compris l'interrogation) pendant toute la durée de son travail. Il est clair que sur un système utilisé activement, cela peut être inacceptable. Les verrous seront considérés séparément, mais pour l'instant, nous nous
limiterons à mentionner l'extension
pg_repack , qui ne verrouille la table que pendant une courte période à la fin du travail.
Équipes similaires
Il existe plusieurs commandes qui reconstruisent également complètement les tables et les index, ce qui est similaire à un nettoyage complet. Tous bloquent complètement le travail avec la table, tous suppriment les anciens fichiers de données et en créent de nouveaux.
La commande CLUSTER est similaire en tout à VACUUM FULL, mais organise en outre physiquement la version des chaînes selon l'un des index disponibles. Cela permet au planificateur d'utiliser plus efficacement l'accès à l'index dans certains cas. Cependant, il faut comprendre que le clustering n'est pas pris en charge: avec les modifications ultérieures de la table, l'ordre physique des versions de ligne sera violé.
La commande REINDEX reconstruit un seul index sur une table. En fait, VACUUM FULL et CLUSTER utilisent cette commande pour reconstruire les index.
La commande TRUNCATE fonctionne logiquement de la même manière que DELETE - elle supprime toutes les lignes de table. Mais DELETE, comme déjà discuté, marque uniquement la version des lignes comme supprimée, ce qui nécessite un nettoyage supplémentaire. TRUNCATE crée juste un nouveau fichier propre. En règle générale, cela fonctionne plus rapidement, mais gardez à l'esprit que TRUNCATE bloquera complètement le travail avec la table pendant toute la durée jusqu'à la fin de la transaction.
À suivre .