Suite à la rencontre "Nouvelles fonctionnalités de PostgreSQL 11"

Aujourd'hui, nous allons parler des fonctionnalités les plus importantes de PostgreSQL 11. Pourquoi seulement à leur sujet - parce que tout le monde n'a pas besoin de certaines fonctionnalités, nous avons donc choisi les plus populaires.

Table des matières




Compilation Jit


PostgreSQL a enfin introduit la compilation JIT, c'est-à-dire la compilation de requêtes en code binaire. Pour ce faire, compilez PostgreSQL avec le support de la compilation JIT (Compile time 1 (--with-llvm)) . Dans le même temps, la machine doit avoir une version LLVM non inférieure à 3.9.

Qu'est-ce qui peut accélérer JIT?

  • RequĂŞtes avec la clause WHERE, c'est-Ă -dire tout ce qui vient après ce mot-clĂ©. Ce n'est pas toujours nĂ©cessaire, mais l'occasion est utile.
  • Calcul de la liste cible: dans la terminologie PostgreSQL, c'est tout ce qui est entre select et from.
  • AgrĂ©gats.
  • Convertir des enregistrements d'une vue Ă  une autre (Projection). Par exemple, lorsque vous appliquez la jointure Ă  deux tables, le rĂ©sultat est un nouveau tuple contenant des champs des deux tables.
  • Tuple se dĂ©formant. L'un des problèmes de toute base de donnĂ©es, au moins minuscule, relationnel, est de savoir comment obtenir un champ Ă  partir d'un enregistrement sur disque. Après tout, il peut y avoir null, ils ont des enregistrements diffĂ©rents et en gĂ©nĂ©ral, ce n'est pas l'opĂ©ration la moins chère.

Compile time 2 signifie que JIT n'est pas utilisé. Dans PostgreSQL, il y a un moment de planification des requêtes, lorsque le système décide ce qui vaut JIT et ce qui ne l'est pas. À ce stade, il exécute les JIT, puis l'exécuteur s'exécute tel quel.

JIT est rendu enfichable. Par défaut, cela fonctionne avec LLVM, mais vous pouvez connecter n'importe quel autre JIT.



Si vous avez compilé PostgreSQL sans prise en charge JIT, la toute première configuration ne fonctionne pas. Options mises en œuvre pour les développeurs, il existe des paramètres pour les fonctions JIT individuelles.

Le prochain point subtil est lié à jit_above_cost. JIT lui-même n'est pas gratuit. Par conséquent, PostgreSQL utilise par défaut l'optimisation JIT si le coût d'une requête dépasse 100 000 perroquets conditionnels, dans lesquels l'explication, l'analyse, etc. sont mesurées. Cette valeur est choisie au hasard, alors faites-y attention.

Mais pas toujours après avoir activé JIT, tout fonctionne immédiatement. Habituellement, tout le monde commence à expérimenter avec JIT en utilisant le tableau select * from où la requête id = 600 et ils échouent. Probablement, il est nécessaire de compliquer en quelque sorte la demande, puis tout le monde génère une base de données géante et compose la demande. En conséquence, PostgreSQL repose sur les capacités du disque, il lui manque la capacité des tampons et caches partagés.

Voici un exemple complètement abstrait. Il y a 9 champs nuls avec des fréquences différentes, de sorte que vous pouvez remarquer l'effet de la déformation du tuple.

select i as x1,
case when i % 2 = 0 then i else null end as x2,
case when i % 3 = 0 then i else null end as x3,
case when i % 4 = 0 then i else null end as x4,
case when i % 5 = 0 then i else null end as x5,
case when i % 6 = 0 then i else null end as x6,
case when i % 7 = 0 then i else null end as x7,
case when i % 8 = 0 then i else null end as x8,
case when i % 9 = 0 then i else null end as x9
into t
from generate_series(0, 10000000) i;

vacuum t;
analyze t;


PostgreSQL a beaucoup de possibilités, et pour voir les avantages de JIT, désactivez les deux premières lignes afin de ne pas interférer et réinitialisez les seuils.

set max_parallel_workers=0;
set max_parallel_workers_per_gather=0;
set jit_above_cost=0;
set jit_inline_above_cost=0;
set jit_optimize_above_cost=0;


Voici la demande elle-mĂŞme:

set jit=off;
explain analyze
select count(*) from t where
sqrt(pow(x9, 2) + pow(x8,2)) < 10000;

set jit=on;
explain analyze
select count(*) from t where
sqrt(pow(x9, 2) + pow(x8,2)) < 10000;


Et voici le résultat:

Planning Time: 0.71 ms
Execution Time: 1986.323 ms

VS

Planning Time: 0.060 ms
JIT:
Functions: 4
Generation Time: 0.911 ms
Inlining: true
Inlining Time: 23.876 ms
Optimization: true
Optimization Time: 41.399 ms
Emission Time: 21.856 ms
Execution Time: 949.112 ms


JIT a contribué à accélérer la demande de moitié. La planification du temps est à peu près la même chose, mais c'est probablement le résultat de la mise en cache de PostgreSQL, alors ignorez-le.

En résumé, il a fallu environ 80 ms à la compilation JIT. Pourquoi JIT n'est-il pas gratuit? Avant d'exécuter la demande, vous devez la compiler, ce qui prend également du temps. Et trois ordres de grandeur de plus que la planification. Pas un plaisir cher, mais il est payant en raison de la durée de l'exécution.

De cette façon, vous pouvez utiliser JIT, bien que ce ne soit pas toujours bénéfique.

Partitionnement


Si vous avez fait attention au partitionnement dans PostgreSQL, vous avez probablement remarqué qu'il a été fait là-bas pour le show. La situation s'est légèrement améliorée dans la version 10, lorsqu'une déclaration déclarative des partitions (sections) est apparue. En revanche, tout est resté le même à l'intérieur et a fonctionné à peu près de la même manière que dans les versions précédentes, c'est-à-dire mauvais.
À bien des égards, ce problème a été résolu par le module pg_pathman, qui a permis de travailler avec des sections et de les couper au moment optimal au moment de l'exécution.

Dans la version 11, le partitionnement est grandement amélioré:

  • Tout d'abord, la table de partition peut avoir une clĂ© primaire, qui doit inclure la clĂ© de partition. En fait, il s'agit soit d'une clĂ© semi-primaire, soit d'une demi-clĂ© primaire. Malheureusement, vous ne pouvez pas y crĂ©er de clĂ© Ă©trangère. J'espère que cela sera corrigĂ© Ă  l'avenir.
  • De plus, il est dĂ©sormais possible de partitionner non seulement par plage, mais Ă©galement par liste et par hachage. Le hachage est assez primitif, le reste de l'expression est pris pour lui.
  • Lors de la mise Ă  jour, la ligne se dĂ©place entre les sections. Auparavant, vous deviez Ă©crire un dĂ©clencheur, mais maintenant cela se fait automatiquement.

La grande question est: combien de sections puis-je avoir? Honnêtement, avec un grand nombre de sections (des milliers et des dizaines de milliers), la fonctionnalité ne fonctionne pas bien. Pg_pathman fait mieux.

Également créé des sections par défaut. Encore une fois, dans pg_pathman, vous pouvez créer automatiquement des sections, ce qui est plus pratique. Ici, tout ce qui n'a pu être poussé quelque part tombe dans la section. Si dans un vrai système pour faire cela par défaut, alors après un certain temps, vous obtenez un tel gâchis, que vous tourmentez pour ratisser.

PostgreSQL 11 est désormais en mesure d'optimiser le partitionnement si deux tables sont jointes par une clé de partition et que les schémas de partitionnement correspondent. Ceci est contrôlé par un paramètre spécial, qui est désactivé par défaut.

Vous pouvez calculer des agrégats pour chaque section séparément, puis additionner. Enfin, vous pouvez créer un index sur la table partitionnée parente, puis des index locaux sur toutes les tables qui y sont connectées seront créés.

Dans la section «Quoi de neuf», une chose merveilleuse est mentionnée - la possibilité de jeter des sections lors de l'exécution d'une demande. Vérifions comment cela fonctionne. Le résultat est un tel tableau:



Nous faisons un type et un tableau de deux colonnes avec une clé primaire, avec une grande colonne série, insérons les données. Nous créons la deuxième table, qui sera partitionnée et sera une copie de la première. Ajoutez la clé primaire à la table partitionnée.



Le tableau comprendra deux types d'entrées: «nounous femmes» et «conducteurs hommes». Et il y aura une conductrice. Nous faisons deux sections, divisons par liste, ajoutons la clé primaire et insérons toutes les données de la table dans laquelle tout cela est généré. Le résultat était complètement inintéressant:



Faites attention à la demande. Nous sélectionnons tout dans une table non partitionnée, nous nous connectons à une table partitionnée. Nous prenons un petit morceau et choisissons un seul type, ils en passent par un. Nous indiquons que la colonne oss doit avoir une valeur. Il s'avère qu'une sélection de pilotes solides.

Lors de l'exécution, nous désactivons spécifiquement la parallélisation, car PostgreSQL 11 par défaut parallélise très activement les requêtes plus ou moins complexes. Si nous regardons le plan d'exécution (expliquer l'analyse), alors on peut voir que le système a ajouté les données dans les deux sections: dans la nounou et dans les chauffeurs, bien que les nounous n'étaient pas là. Il n'y a eu aucun appel au tampon. Temps passé, condition utilisée, bien que PostgreSQL puisse tout comprendre. Autrement dit, la déclaration d'élimination de partition ne fonctionne pas tout de suite. Peut-être que dans les versions suivantes, cela sera corrigé. Dans ce cas, le module pg_pathman dans ce cas fonctionne sans problème.

Indices


  • Optimisation des enchères de manière monotone, c'est-Ă -dire b-tree. Tout le monde sait que lorsque vous insĂ©rez des donnĂ©es Ă  croissance monotone, cela ne s'avère pas très rapide. Maintenant, PostgreSQL est capable de mettre en cache la page de fin d'une manière spĂ©ciale et de ne pas aller de la racine Ă  l'insertion. Cela accĂ©lère considĂ©rablement le travail.
  • PostgreSQL 10 a permis d'utiliser un index de hachage car il a commencĂ© Ă  utiliser WAL (Ă©criture anticipĂ©e du journal). Auparavant, nous avons obtenu la valeur, dĂ©verrouillĂ© la page, renvoyĂ© la valeur. Pour la valeur suivante, vous deviez Ă  nouveau bloquer la page, revenir, dĂ©verrouiller, etc. Maintenant, le hachage est devenu beaucoup plus rapide. Il vous permet de bloquer une page Ă  la fois pour rĂ©cupĂ©rer un enregistrement Ă  partir d'un index de hachage, retourner toutes les valeurs Ă  partir de lĂ  et le dĂ©verrouiller. Maintenant, il est implĂ©mentĂ© pour HASH, GiST et GIN. Ă€ l'avenir, cela sera probablement implĂ©mentĂ© pour SP-GiST. Mais pour BRIN avec sa logique min / max cela ne peut pas ĂŞtre fait en principe.
  • Si vous aviez l'habitude de crĂ©er des index fonctionnels, la mise Ă  jour HOT (Heap Only Tuple) Ă©tait effectivement dĂ©sactivĂ©e. Lorsqu'un enregistrement est mis Ă  jour dans PostgreSQL, une nouvelle copie est rĂ©ellement créée, ce qui nĂ©cessite de coller dans tous les index qui se trouvent dans la table afin que la nouvelle valeur pointe vers le nouveau tuple. Une telle optimisation a Ă©tĂ© mise en Ĺ“uvre depuis longtemps: si la mise Ă  jour ne change pas les champs qui ne sont pas inclus dans les index, et qu'il y a de l'espace libre sur la mĂŞme page, alors les index ne sont pas mis Ă  jour, et dans l'ancienne version de tuple, un pointeur vers la nouvelle version est placĂ©. Cela vous permet de rĂ©duire quelque peu la gravitĂ© du problème avec les mises Ă  jour. Cependant, une telle optimisation ne fonctionnait pas du tout si vous aviez des index fonctionnels. Dans PostgreSQL 11, il a commencĂ© Ă  fonctionner. Si vous avez créé un index fonctionnel et mis Ă  jour un tuple qui ne change pas ce dont dĂ©pend l'index fonctionnel, la mise Ă  jour HOT fonctionnera.

Indices de couverture


Cette fonctionnalité a été implémentée par PostgresPro il y a trois ans, et pendant tout ce temps, PostgreSQL a essayé de l'ajouter. Les index de couverture signifient que vous pouvez ajouter des colonnes supplémentaires à l'index unique, directement dans le tuple d'index.

Pourquoi? Tout le monde aime la numérisation indexée uniquement pour son travail rapide. Pour cela, des indices «couvrant» conditionnellement sont construits:



Mais en même temps, vous devez maintenir l'unicité. Par conséquent, deux index sont en cours de construction, étroits et larges.
L'inconvénient est que lorsque vous appliquez le vide, l'insertion ou la mise à jour à une table, vous devez mettre à jour les deux index. L'insertion dans un index est donc une opération lente. Et l'indice de couverture ne permettra de gérer qu'un seul indice.

Certes, il a certaines limites. Plus précisément, les avantages qui peuvent ne pas être immédiatement compris. Les colonnes c et d du premier index de création ne doivent pas nécessairement être des types scalaires pour lesquels un index b-tree est défini. Autrement dit, ils n'ont pas nécessairement une comparaison plus ou moins. Il peut s'agir de points ou de polygones. La seule chose est que le tuple doit être inférieur à 2,7 Kb, car il n'y a pas de grillage dans l'index, mais vous pouvez rentrer dans ce qui ne peut pas être comparé.

Cependant, à l'intérieur de l'index avec ces colonnes couvertes garanties, aucun calcul n'est effectué lors de la recherche. Cela devrait être fait par un filtre qui se trouve au-dessus de l'index. D'une part, pourquoi ne pas le calculer à l'intérieur de l'index, d'autre part, il s'agit d'un appel de fonction supplémentaire. Mais tout n'est pas aussi effrayant qu'il n'y paraît.

Eh bien, en plus, vous pouvez ajouter ces colonnes couvertes à la clé primaire.

SP GiST


Peu de gens utilisent cet indice car il est assez spécifique. Néanmoins, il est devenu possible de stocker en elle pas tout à fait ce qui a été inséré. Cela fait référence à l'index avec perte, la compression. Prenons l'exemple des polygones. Au lieu de cela, une boîte englobante est placée dans l'index, c'est-à-dire le rectangle minimum qui contient le polygone souhaité. Dans ce cas, nous représentons le rectangle comme un point dans un espace à quatre dimensions, puis nous travaillons avec le quad3 classique, dans un espace à quatre dimensions.

Le SP-GiST a également introduit l'opération "recherche de préfixe". Il retourne vrai si une ligne est le préfixe d'une autre. Ils l'ont présenté non seulement comme ça, mais pour le bien d'une telle demande avec le support de SP-GiST.

SELECT * FROM table WHERE c ^@ „abc“

Dans b-tree, il y a une limite de 2,7 Ko par ligne, mais pas SP-GiST. Certes, PostgreSQL a une limitation: une seule valeur ne peut pas dépasser 1 Go.

Performances


  • Un scan d'index bitmap uniquement est apparu . Il fonctionne de la mĂŞme manière que l'analyse d'index classique, sauf qu'il ne peut garantir aucune commande. Par consĂ©quent, il n'est applicable que pour certains agrĂ©gats comme count (*), car le bitmap n'est pas en mesure de transfĂ©rer des champs de l'index vers l'exĂ©cuteur. Il ne peut que signaler le fait d'un dossier qui remplit les conditions.
  • La prochaine innovation est la mise Ă  jour de la carte de l'espace libre lors de l'application du vide . Malheureusement, aucun des dĂ©veloppeurs de systèmes travaillant avec PostgreSQL ne pense qu'il est nĂ©cessaire de supprimer Ă  la fin du tableau, sinon des trous, de l'espace non allouĂ© apparaissent. Pour suivre cela, nous avons implĂ©mentĂ© FSM, ce qui nous permet de ne pas agrandir la table, mais d'insĂ©rer le tuple dans les vides. Auparavant, cela se faisait avec le vide, mais Ă  la fin. Et maintenant, le vide est capable de le faire dans le processus, et dans les systèmes fortement chargĂ©s, il aide Ă  garder la taille de la table sous contrĂ´le.
  • PossibilitĂ© d'ignorer l'analyse d'index lors de l'exĂ©cution sous vide . Le fait est que tous les index PostgreSQL, selon la thĂ©orie des bases de donnĂ©es, sont appelĂ©s secondaires. Cela signifie que les index sont stockĂ©s loin de la table; les pointeurs y mènent. Le scan d'index uniquement vous permet de ne pas faire ce saut sur des pointeurs, mais de le prendre directement depuis l'index. Mais le vide, qui supprime les enregistrements, ne peut pas les consulter dans l'index et dĂ©cider de les supprimer ou non, simplement parce qu'il n'y a pas de telles donnĂ©es dans l'index. Par consĂ©quent, le vide est toujours effectuĂ© en deux passes. Tout d'abord, il parcourt la table et dĂ©couvre ce qu'il doit supprimer. Ensuite, il va aux index attachĂ©s Ă  cette table, supprime les enregistrements qui se rĂ©fèrent aux trouvĂ©s, revient Ă  la table et supprime ce qu'il allait faire. Et l'Ă©tape de passage aux indices n'est pas toujours requise.

    Si, depuis le dernier vide, il n'y a pas eu de suppression ou de mise à jour, vous n'avez aucun enregistrement mort, vous n'avez pas besoin de les supprimer. Dans ce cas, vous ne pouvez pas accéder à l'index. Il existe des subtilités supplémentaires, b-tree ne supprime pas ses pages immédiatement, mais en deux passes. Par conséquent, si vous avez supprimé un grand nombre de données dans le tableau, vous devez effectuer un vide. Mais si vous voulez libérer de l'espace dans les indices, passez l'aspirateur deux fois.

    Quelqu'un sera surpris, quel est ce tableau dans lequel il n'y a pas eu de suppression ou de mise à jour? En fait, beaucoup y font face, ne pense tout simplement pas. Ce ne sont que des tableaux à ajouter, où, par exemple, des journaux sont ajoutés. Chez eux, l'enlèvement est extrêmement rare. Et cela économise considérablement la durée de vide / autovacuum, réduit la charge sur le disque, l'utilisation de caches et ainsi de suite.
  • Engagez simultanĂ©ment des transactions concurrentielles . Ce n'est pas une innovation, mais une amĂ©lioration. Maintenant, PostgreSQL dĂ©tecte qu'il va valider maintenant et retarde la validation de la transaction en cours, attendant le reste des validations. Veuillez noter que cette fonction a peu d'effet si vous avez un petit serveur avec 2 Ă  4 cĹ“urs.
  • postgres_fdw (wrappers de donnĂ©es Ă©trangères) . FDW est un moyen de connecter une source de donnĂ©es externe pour qu'elle ressemble Ă  un vĂ©ritable post-Congrès. postgres_fdw vous permet de connecter une table d'une instance voisine Ă  votre instance, et elle ressemblera presque Ă  une vraie. DĂ©sormais, l'une des restrictions de mise Ă  jour et de suppression a Ă©tĂ© supprimĂ©e. PostgreSQL peut souvent deviner que vous devez envoyer des donnĂ©es brutes. La façon d'exĂ©cuter la demande de jointure est assez simple: nous l'exĂ©cutons sur notre machine, nous retirons la table de l'instance Ă  l'aide de FDW, dĂ©couvrons la clĂ© primaire id que nous devons supprimer, puis appliquons la mise Ă  jour et / ou la suppression, c'est-Ă -dire les donnĂ©es que nous allons et venons . Maintenant, c'est possible. Bien sĂ»r, si les tables sont sur des machines diffĂ©rentes, ce n'est pas si facile, mais FDW vous permet de faire effectuer des opĂ©rations Ă  la machine distante, et nous avons juste attendu.
  • toast_tuple_target . Il y a des situations oĂą les donnĂ©es dĂ©passent lĂ©gèrement les limites après lesquelles il est nĂ©cessaire de griller, mais en mĂŞme temps, le grillage de ces valeurs n'est pas toujours agrĂ©able. Supposons que vous ayez une limite de 90 octets et que vous en ayez besoin de 100. Vous devez dĂ©marrer le toast pour 10 octets, les ajouter sĂ©parĂ©ment, puis lorsque vous sĂ©lectionnez ce champ, vous devez accĂ©der Ă  l'index de toast, savoir oĂą se trouvent les donnĂ©es nĂ©cessaires, aller Ă  la table de toasts, recueillir et donner.

Maintenant, avec l'aide d'un réglage fin, vous pouvez modifier ce comportement pour la base de données entière ou une table distincte afin que ces petites sorties ne nécessitent pas l'utilisation de toast. Mais vous devez comprendre ce que vous faites, sans cela, rien ne fonctionnera.

WAL


  • WAL (Write ahead log) est un journal d'Ă©criture anticipĂ©e. La taille du segment WAL est dĂ©sormais dĂ©finie dans initdb. Dieu merci, pas lors de la compilation.
  • La logique a Ă©galement changĂ©. Auparavant, l'ensemble des segments WAL Ă©tait enregistrĂ© Ă  partir de l'avant-dernier point de contrĂ´le, et maintenant Ă  partir du dernier. Cela peut rĂ©duire considĂ©rablement la quantitĂ© de donnĂ©es stockĂ©es. Mais si vous avez une base de donnĂ©es de 1 To et TPS = 1, c'est-Ă -dire une demande par seconde, alors vous ne verrez pas la diffĂ©rence.

Sauvegarde et réplication


  • Tronquer est apparu dans la rĂ©plication logique . C'Ă©tait la dernière des opĂ©rations DML qui ne se reflĂ©tait pas dans la rĂ©plication logique. Maintenant rĂ©flĂ©chi.
  • Un message sur la prĂ©paration est apparu dans la rĂ©plication logique . Vous pouvez maintenant intercepter la transaction de prĂ©paration, une validation en deux phases dans la rĂ©plication logique. Ceci est mis en Ĺ“uvre pour la construction de clusters - hĂ©tĂ©rogènes, homogènes, Ă©clatĂ©s et non ombrĂ©s, multimaĂ®tre et ainsi de suite.
  • Exception des tables temporaires et non enregistrĂ©es de pg_basebackup . Beaucoup se sont plaints que pg_basebackup inclut les tables listĂ©es. Et en les excluant, nous rĂ©duisons la taille de la sauvegarde. Mais Ă  condition que vous utilisiez des tables temporaires et non enregistrĂ©es, sinon cette option vous sera inutile.
  • ContrĂ´le Checksumma dans la rĂ©plication en streaming (pour les tables) . Cela vous permet de comprendre ce qui est arrivĂ© Ă  votre rĂ©plique. Jusqu'Ă  prĂ©sent, la fonction n'est implĂ©mentĂ©e que pour les tables.
  • Il y a eu une promotion des positions des emplacements de rĂ©plication . Comme toujours, vous ne pouvez avancer que vers l'arrière, uniquement s'il y a un WAL. De plus, vous devez très bien comprendre ce que vous en faites et pourquoi. Ă€ mon avis, il s'agit davantage d'une option de dĂ©veloppement, mais ceux qui utilisent la rĂ©plication logique pour certaines applications exotiques peuvent en profiter.

Pour dba


  • Modifier la table, ajouter une colonne, non null par dĂ©faut X , Ă©crire la table entière. Il y a un petit supplĂ©ment pour cela: la valeur par dĂ©faut est stockĂ©e sĂ©parĂ©ment. Si vous choisissez un tuple et avez besoin de cette colonne, PostgreSQL est alors obligĂ© de suivre un chemin de codage supplĂ©mentaire pour extraire une valeur temporaire, la remplacer par tuple et vous la donner. NĂ©anmoins, on peut vivre avec.
  • Vide / analyse . Auparavant, vous ne pouviez appliquer le vide ou analyser qu'Ă  une base de donnĂ©es entière ou Ă  une seule table. Maintenant, il est possible de le faire sur plusieurs tables, avec une seule commande.

Exécution parallèle


  • Construction parallèle d'index b-tree . Dans la version 11, il est devenu possible d'intĂ©grer des index b-tree dans plusieurs travailleurs. Si vous avez une très bonne machine, de nombreux disques et de nombreux cĹ“urs, vous pouvez crĂ©er des index en parallèle, ce qui promet une augmentation notable des performances.
  • Hachage d'une connexion parallèle Ă  l'aide d'une table de hachage partagĂ©e pour les exĂ©cuteurs . , -. , . - , . .
  • , union, create table as, select create materialized view!
  • - (limit) . .

:

alter table usr reset (parallel_workers)
create index on usr(lower((so).occ)) — 2
alter table usr set (parallel_workers=2)
create index on usr(upper((so).occ)) — 1.8


parallel worker. . 16 4 ( ) 2 ., — 1,8 . , , . , .

:

explain analyze
select u1.* from usr u, usr1 u1 where
u.id=u1.id+0


, . , user — , . . , , .

, PostgreSQL 11 .



1425 , 1,5 . 1,4 . 2 . , 9.6 : 1 — 1 ., 2 1 . , 10 tuple. 11 . : user, batch, x-scan append .

:



. 211 , 702 . , 510 1473. , 2 .

parallel hash join. . — 4. , .

parallel index scan . batch . Qu'est-ce que cela signifie? hash join, . user . , parallel hash, .

1 . , OLAP-, OLTP . OLTP , .


.

  • . , . , «» «», index scan, . (highly skewed data), , . . , , .
  • «», .

Window-


SQL:2011, .


, , . , , , , , .

websearch, . , . , .

# select websearch_to_tsquery('dog or cat');
----------------------
'dor' | 'cat'
# select websearch_to_tsquery('dog -cat');
----------------------
'dor' & !'cat'
# select websearch_to_tsquery('or cat');
----------------------
'cat'


— dog or cat — . Websearch . | , . “or cat”. , . websearch “or” . , -, .

Websearch — . : , . , .

Json(b)


10- , 11- . json json(b), tsvector. ( json(b)) - . , , , bull, numeric, string, . .

# select jsonb_to_tsvector
('{"a":"texts", "b":12}', '"string"');
-------------------
'text':1
# select jsonb_to_tsvector
('{"a":"texts", "b":12}', '["string", "numeric"]');
-------------------
'12':3 'text':1


json(b), . , , , .

PL/*


.

CREATE PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
FOR i IN 0..9 LOOP
INSERT INTO test1 (a) VALUES (i);
IF i % 2 = 0 THEN
COMMIT;
ELSE
ROLLBACK;
END IF;
END LOOP;
END
$$;
CALL transaction_test1();


call, , . . . select, insert .

, , PostgreSQL . Perl, Python, TL PL/pgSQL. Perl sp begin, .

PL/pgSQL : , .

pgbench


pgbench ICSB bench — , , . if, , . case, - . --init-steps , , .

random-seed. zipfian- . / — , . - , , - , .

, , - .

PSQL


, PSQL, . exit quit.

  • — copy, 2 32 . copy : 2 32 - . , 2 31 2 32 copy . 64- , 2 64 .
  • POSIX : NaN 0 = 1 1 NaN = 1.

Source: https://habr.com/ru/post/fr414031/


All Articles