web-dev-qa-db-fra.com

La recherche d'index serait-elle sensiblement plus rapide avec char vs varchar lorsque toutes les valeurs sont de 36 caractères

J'ai un schéma hérité (avertissement!) Qui utilise un identifiant généré par hachage pour la clé primaire de toutes les tables (il y en a beaucoup). Un exemple d'un tel identifiant est:

922475bb-ad93-43ee-9487-d2671b886479

Il n'y a aucun espoir possible de changer cette approche, mais les performances avec l'accès à l'index sont médiocres. Mis à part la myriade de raisons pour lesquelles cela pourrait être, il y a une chose que j'ai remarqué qui semblait moins qu'optimale - bien que toutes les valeurs d'ID dans toutes les nombreuses tables aient exactement 36 caractères, le type de colonne est varchar(36), - paschar(36).

La modification des types de colonnes à longueur fixe char(36) offrirait-elle des avantages de performance d'index significatif, au-delà de la très faible augmentation du nombre d'entrées par page d'index, etc.?

C'est-à-dire que les postgres fonctionnent beaucoup plus rapidement lorsqu'il s'agit de types de longueur fixe que de types de longueur variable?

Veuillez ne pas mentionner l'économie de stockage minuscule - cela n'aura pas d'importance par rapport à la chirurgie nécessaire pour effectuer la modification des colonnes.

33
Bohemian

Non. Aucun gain du tout . Le manuel indique explicitement :

Astuce: Il n'y a pas de différence de performances entre ces trois types , à part un espace de stockage accru lors de l'utilisation du type à remplissage vierge et quelques cycles CPU supplémentaires pour vérifier la longueur lors du stockage dans une colonne à longueur limitée. Bien que character(n) présente des avantages en termes de performances dans certains autres systèmes de base de données, il n'y en a pas dans PostgreSQL; en fait, character(n) est généralement la plus lente des trois en raison de ses coûts de stockage supplémentaires. Dans la plupart des situations, text ou character varying Doit être utilisé à la place .

Accentuation sur moi.

char(n) est un type largement obsolète et inutile. Restez avec varchar(n). Sans avoir besoin d'appliquer une longueur maximale, varchar ou text sont un tout petit peu plus rapides. (Vous ne pourrez pas mesurer une différence.)

Si toutes les chaînes ont exactement 36 caractères, il n'y a aucun enregistrement de stockage dans les deux sens, pas même un minuscule. Les deux ont exactement la même taille sur le disque et dans la RAM. Vous pouvez tester avec pg_column_size() (sur une expression et sur une colonne de table).

Et si toutes les chaînes doivent ont 36 caractères, faites plutôt text avec une contrainte CHECK (length(col) = 36) imposant exact longueur, pas varchar(36) seulement en appliquant max. longueur.

En relation:

Vous n'avez pas demandé d'autres options , mais j'en mentionnerai deux:

  1. COLLATION - sauf si vous exécutez votre base de données avec le classement "C" =. L'assemblage est souvent négligé et peut-être coûteux. Puisque vos chaînes ne semblent pas avoir de sens dans un langage naturel, il est probablement inutile de suivre les règles COLLATION. En relation:

    Benchmark étendu comparant (entre autres) l'effet de COLLATE "C" Sur les performances:

  2. [~ # ~] uuid [~ # ~] , évidemment. Votre chaîne ressemble étrangement à un UUID (32 chiffres hexadécimaux plus 4 délimiteurs). Il serait beaucoup plus efficace de les stocker en tant que type de données réel uuid, qui est plus rapide de plusieurs façons et n'occupe que 16 octets - par opposition à 37 octets dans RAM pour char(36) ou varchar(36) (stocké sans délimiteurs, juste les 32 caractères définissant), ou 33 octets sur le disque. Mais remplissage d'alignement entraînerait 40 octets dans les deux cas dans de nombreux cas.) COLLATION ne serait pas non plus pertinent pour le type de données uuid.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid
    

    Cela peut être utile (derniers chapitres):

    Voir également:

44
Erwin Brandstetter