web-dev-qa-db-fra.com

Clé primaire UUID dans Postgres, quel impact sur les performances?

Je m'interroge sur l'impact sur les performances de l'utilisation d'un UUID non séquentiel comme clé primaire dans une table qui deviendra assez volumineuse dans PosgreSQL.

Dans les SGBD qui utilisent le stockage en cluster pour les enregistrements de table, il est évident que l'utilisation d'un UUID va augmenter le coût des insertions en raison de la nécessité de lire sur le disque pour trouver la page de données dans laquelle effectuer l'insertion, une fois que la table est trop grande garder en mémoire. Si je comprends bien, Postgres ne maintient pas le regroupement de lignes sur les insertions, donc j'imagine que dans Postgres, l'utilisation d'un PK UUID ne nuit pas aux performances de cette insertion.

Mais je pense que cela rend l'insertion dans l'index que la contrainte de clé primaire crée beaucoup plus cher une fois que la table est grande, car elle devra être constamment lue sur le disque pour mettre à jour l'index lors de l'insertion de nouvelles données. Alors qu'avec une clé séquentielle, l'index ne sera mis à jour qu'à la pointe qui sera toujours en mémoire.

En supposant que je comprenne correctement l'impact sur les performances de l'index, existe-t-il un moyen de remédier à cela ou les UUID ne sont-ils tout simplement pas un bon PK sur une grande table non partitionnée?

30
philofinfinitejest

Si je comprends bien, Postgres ne conserve pas le regroupement des lignes sur les insertions

C'est correct pour le moment. Malheureusement.

j'imagine donc que dans Postgres, l'utilisation d'un UUID PK ne nuit pas aux performances de cet insert.

Il a toujours un coût de performance en raison de la nécessité de maintenir le PK, et parce que le tuple inséré est plus gros.

  • L'uuid est 4 fois plus large qu'une clé synthétique d'entier 32 bits typique, donc la ligne à écrire est 12 octets plus grande et vous pouvez insérer moins de lignes dans une quantité donnée de RAM

  • L'index b-tree qui implémente la clé primaire sera 4x plus volumineux (par rapport à une clé 32 bits), prenant plus de temps à rechercher et nécessitant plus de mémoire pour mettre en cache. Il a également besoin de fractionnements de page plus fréquents.

  • Les écritures auront tendance à être aléatoires dans les index, pas à ajouter aux lignes chaudes récemment consultées

existe-t-il un moyen de remédier à [l'impact des performances sur l'index] ou les UUID ne sont-ils tout simplement pas un bon PK sur une grande table non partitionnée?

Si vous avez besoin d'une clé UUID, vous avez besoin d'une clé UUID. Vous ne devriez pas en utiliser une si vous n'en avez pas besoin, mais si vous ne pouvez pas compter sur une source centrale de clés synthétiques et qu'il n'y a pas de clé naturelle appropriée à utiliser, c'est toujours le chemin à parcourir.

Le partitionnement n'aidera pas beaucoup sauf si vous pouvez limiter les écritures à une partition. De plus, vous ne pourrez pas utiliser utilement l'exclusion de contrainte sur les recherches de la clé si vous n'écrivez qu'une seule partition à la fois, vous devrez donc toujours rechercher tous les index des partitions pour une clé lorsque vous effectuez des requêtes. Je peux seulement voir qu'il est utile si votre UUID fait partie d'une clé composite et que vous pouvez partitionner sur l'autre partie de la clé composite.

18
Craig Ringer

Il convient de mentionner que vous obtiendrez plus de WAL générés si vous avez un index btree sur la colonne UUID avec full_page_writes option activée. Cela se produit en raison du caractère aléatoire de l'UUID - les valeurs ne sont pas séquentielles, donc chaque insert est susceptible de toucher une page de feuille d'index de feuille complètement nouvelle. Vous pouvez en lire plus dans Sur l'impact des écritures pleine page article.

1
pensnarik