Journal PostgreSQL : ne faites pas ça !

Posté par  (site web personnel, Mastodon) . Licence CC By‑SA.
Étiquettes :
47
8
jan.
2024

Le wiki officiel de PostgreSQL a une page assez méconnue et pourtant si utile que tout gros outil, en particulier ceux avec de l’historique, devraient avoir aussi. Cette page, c’est :

Don’t Do This

Comme le dit le titre, cette page est une liste de possibilités offertes par PostgreSQL à ne pas utiliser, au moins pas sans y réfléchir à deux fois. Les pièges peuvent venir de comportements dépréciés, particulièrement peu clairs ou importés d’autres SGBD. Chaque cas indique aussi dans quels cas on peut utiliser la fonctionnalité, s’il y en a.

Quelques exemples :


Connaissez-vous d’autres outils qui ont une page quasi-officielle de « mauvaises pratiques et pièges à éviter » du même genre que celle-ci ?

  • # GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY

    Posté par  . Évalué à 3.

    Je ne connaissais pas cette possibilité à la place d'une bonne vieille séquence…
    https://www.2ndquadrant.com/en/blog/postgresql-10-identity-columns/

  • # don't do this

    Posté par  . Évalué à 3.

    Petit moment nostalgie sur le "don't do this" et c'est parti en vrille au bureau :

    Hi,

    This is the "PRE-QU-EL" Cloud Superstar,
    and i've an important message to all our users.

    Cloud superstar are professionally trained dba.
    The conf we set in our prod take years of practice to perfect and to do safely.
    I urge all of our Cloud fans to never try to copy what we do in prod at work or at home.

    Please stay safe and don't try this.

    la réf pour les vieux ou les trop jeunes : https://www.dailymotion.com/video/x7v5jl

  • # varchar(n)

    Posté par  . Évalué à 3.

    N’utilisez pas varchar(n) par défaut : la contrainte de longueur de champ n’est pas obligatoire (contrairement à d’autres SGBD) et, si le champ a un besoin fonctionnel d’être contraint en longueur, il y a des manières plus efficaces d’y parvenir.

    Dans l'explication, la seule raison qui est donnée est métier : utiliser plutôt une check constraint car si le nombre de caractères devient trop court, ça évite de péter la table (add column, update, drop column).

    ça ne parle pas des perfs donc le texte sous-entendant que :

    • 3 colonnes varchar + check constraint avec length() <= 30
    • 3 colonnes varchar(30)

    sur quelques millions de lignes et un select col1, col2, col3 where limit 20, ça donne les mêmes perfs ?

    Qqun a testé ?

    • [^] # Re: varchar(n)

      Posté par  (site web personnel, Mastodon) . Évalué à 4. Dernière modification le 08 janvier 2024 à 20:01.

      Je pensais que que la question des performances était évoquée dans ce wiki et en fait non, c’était dans cette réponse, et j’avoue ne pas être allé éplucher tous les lien ni refaire des tests poussés pour savoir ce qu’il en est.

      PS : la notion d’efficacité n’est pas équivalente à celle de performances. L’efficacité inclus les performances, mais aussi la maintenabilité, la stabilité à long terme (cf la liste de problèmes induits par varchar(n) et les bugs corrigés à ce sujet), etc. D’autre part, si impact il y a en terme de performances, je soupçonne que c’est à l’insertion/mise à jour et pas à la sélection qu’il est visible.

      La connaissance libre : https://zestedesavoir.com

      • [^] # Re: varchar(n)

        Posté par  (site web personnel, Mastodon) . Évalué à 2. Dernière modification le 08 janvier 2024 à 20:10.

        PPS : un autre aspect de l’efficacité, c’est que PostgreSQL ne fait pas de différence de traitement selon la taille des chaines de caractères, contrairement à par exemple Oracle qui a un fonctionnement très différent sur les chaines de moins de 4000 (VARCHAR2) et de plus de 4000 caractères (CLOB) (en admettant que cette limitation soit encore d’actualité ?). Donc, ça peut avoir du sens de limiter Oracle (à 4000 si tu veux vraiment mettre une limite haute), mais pas PostgreSQL, du moins pas sur ce critère là. De même, mettre une limite ne permet pas de gagner en espace de stockage (en admettant un frontal correct qui va interdire de stocker n’importe quoi dans ces champs).

        La connaissance libre : https://zestedesavoir.com

        • [^] # Re: varchar(n)

          Posté par  . Évalué à 6.

          Moui, mais dans les faits, quand les données d'une ligne dépassent une certaine taille, Postgre crée à côté une table "TOAST", et ne stocke dans l'enregistrement de la table de données que le pointeur vers le bon enregistrement dans la table TOAST.

          Du coup, garder un bon contrôle de la taille maximum d'un enregistrement reste utile. Et c'est plus facile avec varchar(n) qu'avec varchar.

          Par ailleurs, quand tu bosses chez un éditeur, Postgre n'est peut-être qu'un des SGBDR que tu dois supporter. Et donc, tu veux pas nécessairement t'amuser à dire "alors, je fais un varchar(30) sur MSSQL, MySql, mais un varchar tout court sur Postgre".

          Les esprits chagrins me diront "oui, mais sur Oracle de toute façon tu vas faire un varchar2(30)", mais il me semble que même Oracle a fini par prendre une bonne décision et dire que "OK, varchar et varchar2, c'est finalement pareil". Avec le bémol que ça fait 15 ans qu'ils disent "faites gaffe, on va finir par s'en servir pour faire autre chose".

          Concernant la limite à 4000 caractères sur Oracle, a priori on peut la pousser (via un paramètre d'init) à 32767 d'après la doc, mais j'ai jamais essayé.


          En tout cas, j'ai été vraiment très surpris de ce paragraphe sur varchar vs varchar(n), et ça me donne à réfléchir. Notamment sur le point qu'ils lèvent sur "potentielle non utilisation d'index si le paramètre a été reçu sous forme de varchar alors que la colonne est un char(n)". A mon sens c'est un bug qu'ils devraient corriger.

          Egalement, j'avais pas conscience que "SERIAL" ne devrait plus être utilisé.

          Au final, une très bonne lecture, même si je suis pas d'accord avec tout.

          • [^] # Re: varchar(n)

            Posté par  . Évalué à 3.

            Merde, trop long à modifier. L'histoire d'index, c'est pour char vs char(n).

          • [^] # Re: varchar(n)

            Posté par  (site web personnel, Mastodon) . Évalué à 4.

            Du coup, garder un bon contrôle de la taille maximum d'un enregistrement reste utile. Et c'est plus facile avec varchar(n) qu'avec varchar.

            Pour moi il faut surtout comprendre que, dans le cas général, utiliser varchar plutôt que varchar(n) est préférable. D’ailleurs la règle est « Don't use varchar(n) by default » et pas « Don't use varchar(n) » ; et donc que sauf cas particuliers, une conception à base de varchar ou text sans limites avec des varchar(n) là ou c’est nécessaire posera moins de problèmes (en général, pas seulement de performance) qu’une conception avec des varchar(n) partout. Le wiki parle ici d’éviter une « optimisation prématurée » , si le cas que tu décris peut poser de réels problèmes de performances, soit les concepteurs l’ont pris en compte en amont en connaissance de cause, soit il va être mesurable et corrigé.

            Comme d’habitude avec les pages de conseils (à faire ou à éviter) des documentations, ça n’est pas une liste de règles à appliquer sans réfléchir. D’ailleurs la plupart des règles données ont une section « quand utiliser quand même cette fonctionnalité » qui contient autre chose que « jamais ».

            La connaissance libre : https://zestedesavoir.com

            • [^] # Re: varchar(n)

              Posté par  . Évalué à 4.

              Merci pour ce journal et le lien.
              Juste une remarque de forme, tu as écrit « comportements dépréciés » mais la traduction correcte de "deprecated" (qui est un faux-ami) c'est tout simplement "obsolète".

              • [^] # Re: varchar(n)

                Posté par  (site web personnel, Mastodon) . Évalué à 4.

                Merci, je sais, et honnêtement je m’en fiche, c’est un journal écrit sur un coin de table en 5 minutes, dont le seul but est que les gens aillent voir le lien. Donc tant pis s’il jargonne (parce que dans ce contexte on est plus dans du jargon que dans un vrai contresens).

                Par exemple, la répétition dans «  cette structure du SQL a des comportements particulièrement contre-intuitifs, en particulier dès que des valeurs null sont en jeu. » me gêne davantage. Dans un texte vaguement soigné, les deux auraient été corrigés.

                La connaissance libre : https://zestedesavoir.com

            • [^] # Re: varchar(n)

              Posté par  (site web personnel) . Évalué à 2.

              Oui c'est surtout que varchar(..) varchar et text c'est exactement la meme même chose… il n'y a aucune optimisation en plus.
              Et si tu veux limiter la taille parce que tu te dis que c'est "business nécessaire", beh tu ajoute un CHECK, qui te permet de l'enlever au besoin, ou de gérer comme il se doit.

              donc ouste le varchar(12) et bonjour text :) c'est plus simple a lire (spécialement quand tu débarques)

          • [^] # Re: varchar(n)

            Posté par  . Évalué à 2.

            Hello

            il faut éviter de dire "postgre" :P

            https://www.cybertec-postgresql.com/en/the-shibboleth-of-postgresql/

            TLDR : Postgres tire son nom de la base de données Ingres, il faut donc conserver le "s" quand on retire le "SQL" final, même si les deux "s" sont fusionnés dans le nom complet.

  • # nginx

    Posté par  (site web personnel, Mastodon) . Évalué à 10.

    Connaissez-vous d’autres outils qui ont une page quasi-officielle de « mauvaises pratiques et pièges à éviter » du même genre que celle-ci ?

    Nginx a une page de doc littéralement consacrée à cela : https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/.

  • # Long post regarding Oracle

    Posté par  . Évalué à -3.

    https://asktom.oracle.com/ords/f?p=100:11:13524442248473::::P11_QUESTION_ID:442029737684

    En gros:

    "explain the diff between IN and EXISTS and NOT IN
    and NOT EXIST"

    dans SQL ANSI.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.