PostgreSQL 10 : Amélioration des performances

oct. 4, 2017·
Adrien Nayrat
Adrien Nayrat
· 6 min. de lecture
post Linux

La sortie de la version 10 approche à grands pas, elle est prévue pour demain : Voir ce commit

Cette nouvelle version inclue des fonctionnalités très attendues comme :

  • La réplication logique
  • Le partitionnement natif
  • Amélioration du parallélisme
  • Statistiques multi-colonnes

Pour une liste exhaustive voir :

Dans cet article je vais vous présenter des améliorations sur les performances qui ne sont pas listées dans les releases notes! Aussi surprenant que cela puisse paraître, la communauté ne liste pas ce genre d’améliorations : elles ne représentent pas un changement significatif du point de vue de l’utilisateur.

Bruce Momjian me l’a gentiment rappelé quand j’ai demandé s’il était possible d’indiquer ces améliorations : https://www.postgresql.org/message-id/flat/f6949bce-068f-5de5-fd62-5c1e45a611fa%40dalibo.com#f6949bce-068f-5de5-fd62-5c1e45a611fa@dalibo.com

Réécriture d’une partie de l’exécuteur

Andres Freund a réécris une partie de l’exécuteur :

 1commit b8d7f053c5c2bf2a7e8734fe3327f6a8bc711755
 2Author: Andres Freund <andres@anarazel.de>
 3AuthorDate: Tue Mar 14 15:45:36 2017 -0700
 4Commit: Andres Freund <andres@anarazel.de>
 5CommitDate: Sat Mar 25 14:52:06 2017 -0700
 6
 7Faster expression evaluation and targetlist projection.
 8
 9This replaces the old, recursive tree-walk based evaluation, with
10 non-recursive, opcode dispatch based, expression evaluation.
11 Projection is now implemented as part of expression evaluation.
12
13This both leads to significant performance improvements, and makes
14 future just-in-time compilation of expressions easier.
15
16The speed gains primarily come from:
17 - non-recursive implementation reduces stack usage / overhead
18 - simple sub-expressions are implemented with a single jump, without
19 function calls
20 - sharing some state between different sub-expressions
21 - reduced amount of indirect/hard to predict memory accesses by laying
22 out operation metadata sequentially; including the avoidance of
23 nearly all of the previously used linked lists
24 - more code has been moved to expression initialization, avoiding
25 constant re-checks at evaluation time
26...

Comme vous pouvez le lire, ce commit apporte un gain sur les performances mais facilitera la mise en œuvre du « JIT » pour « Just In Time » : Compilation à la volée) dans les futures versions.

Le thread mentionne des gains significatifs : https://www.postgresql.org/message-id/20170314065259.ffef4tfhgbsaieoe%40alap3.anarazel.de

Améliorations sur les tri externes

Les commits suivants améliorent très significativement les tris externes :

 1commit e94568ecc10f2638e542ae34f2990b821bbf90ac
 2Author: Heikki Linnakangas <heikki.linnakangas@iki.fi>
 3Date: Mon Oct 3 13:37:49 2016 +0300
 4
 5Change the way pre-reading in external sort's merge phase works.
 6
 7 Don't pre-read tuples into SortTuple slots during merge. Instead, use the
 8 memory for larger read buffers in logtape.c. We're doing the same number
 9 of READTUP() calls either way, but managing the pre-read SortTuple slots
10 is much more complicated. Also, the on-tape representation is more compact
11 than SortTuples, so we can fit more pre-read tuples into the same amount
12 of memory this way. And we have better cache-locality, when we use just a
13 small number of SortTuple slots.
14...
 1commit 24598337c8d214ba8dcf354130b72c49636bba69
 2Author: Heikki Linnakangas <heikki.linnakangas@iki.fi>
 3Date: Sun Sep 11 16:27:27 2016 +0300
 4
 5Implement binary heap replace-top operation in a smarter way.
 6
 7 In external sort's merge phase, we maintain a binary heap holding the next
 8 tuple from each input tape. On each step, the topmost tuple is returned,
 9 and replaced with the next tuple from the same tape. We were doing the
10 replacement by deleting the top node in one operation, and inserting the
11 next tuple after that. However, you can do a "replace-top" operation more
12 efficiently, in one "sift-up". A deletion will always walk the heap from
13 top to bottom, but in a replacement, we can stop as soon as we find the
14 right place for the new tuple. This is particularly helpful, if the tapes
15 are not in completely random order, so that the next tuple from a tape is
16 likely to land near the top of the heap.

Pour faire simple, les algorithmes ont été revus et permettent de mieux exploiter les caches. Là aussi les gains sont très significatifs, on a constaté des tris deux fois plus rapides sur certaines plateformes (le résultat peut dépendre de beaucoup de paramètres, notamment la taille du cache du processeur etc).

Ainsi les tris qui ne peuvent pas tenir en mémoire et qui doivent donc être  effectués sur disque devraient être beaucoup plus rapides. Par exemple, lors de la création d’un index sur une table volumineuse 🙂

Améliorations sur les fonctions de hashages

Andreus Freund (encore!) a revu les fonctions de hashage et à nouveau les gains sont impressionnants.

Peter Geoghegan en fait mention dans cette conférence :

https://speakerdeck.com/peterg/sort-hash-pgconfus-2017

(Voir le slide 52)

Andres Freund a mis en place une infrastructure :

 1commit b30d3ea824c5ccba43d3e942704f20686e7dbab8
 2Author: Andres Freund ><andres@anarazel.de>
 3Date:   Fri Oct 14 16:05:30 2016 -0700
 4
 5    Add a macro templatized hashtable.
 6
 7    dynahash.c hash tables aren't quite fast enough for some
 8    use-cases. There are several reasons for lacking performance:
 9    - the use of chaining for collision handling makes them cache
10      inefficient, that's especially an issue when the tables get bigger.
11    - as the element sizes for dynahash are only determined at runtime,
12      offset computations are somewhat expensive
13    - hash and element comparisons are indirect function calls, causing
14      unnecessary pipeline stalls
15    - it's two level structure has some benefits (somewhat natural
16      partitioning), but increases the number of indirections
17    to fix several of these the hash tables have to be adjusted to the
18    individual use-case at compile-time. C unfortunately doesn't provide a
19    good way to do compile code generation (like e.g. c++'s templates for
20    all their weaknesses do).  Thus the somewhat ugly approach taken here is
21    to allow for code generation using a macro-templatized header file,
22    which generates functions and types based on a prefix and other
23    parameters.
24
25    Later patches use this infrastructure to use such hash tables for
26    tidbitmap.c (bitmap scans) and execGrouping.c (hash aggregation,
27    ...). In queries where these use up a large fraction of the time, this
28    has been measured to lead to performance improvements of over 100%.
29...

Oui vous lisez bien « improvements of over 100% » :)

Ensuite il a utilisé cette infrastructure pour améliorer les bitmap scan et les jointures par hash join :

1commit 75ae538bc3168bf44475240d4e0487ee2f3bb376
2Author: Andres Freund <andres@anarazel.de>
3Date:   Fri Oct 14 16:05:30 2016 -0700
4
5    Use more efficient hashtable for tidbitmap.c to speed up bitmap scans.
6
7    Use the new simplehash.h to speed up tidbitmap.c uses. For bitmap scan
8    heavy queries speedups of over 100% have been measured. Both lossy and
9    exact scans benefit, but the wins are bigger for mostly exact scans.

Encore un gain de 100% :)

Enfin, cette même infrastructure a été utilisée pour améliorer les performances sur les GROUPING SETS (ça, c’est bien mentionné dans les releases notes):

1commit 5dfc198146b49ce7ecc8a1fc9d5e171fb75f6ba5
2Author: Andres Freund <andres@anarazel.de>
3Date:   Fri Oct 14 17:22:51 2016 -0700
4
5    Use more efficient hashtable for execGrouping.c to speed up hash aggregation.
6
7    The more efficient hashtable speeds up hash-aggregations with more than
8    a few hundred groups significantly. Improvements of over 120% have been
9    measured.

Ici le commit mentionne un gain de 120% :)

Globalement, il faut se dire que chaque nouvelle version apporte des gains en performance même s’ils ne sont pas mentionnés dans les Releases Notes. Ainsi, je vous encourage vivement à faire vos propres tests pour comparer les performances.

La version 10 marque un vrai tournant, PostgreSQL devient vraiment taillé pour s’attaquer aux grosses volumétries (et ce n’est pas fini :) ).

Adrien Nayrat
Auteurs
Expert DBA PostgreSQL

J’ai occupé pendant 7 ans divers postes d’ingénieur système et réseau. Et c’est à partir de 2013 que j’ai commencé à mettre les doigts dans PostgreSQL. J’ai occupé des postes de consultant, formateur, mais également DBA de production (Doctolib, Peopledoc).

Ce blog me permet de partager mes connaissances et trouvailles, ainsi que mes interventions et conférences.