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 :
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 :
-
N’utilisez pas
NOT IN
: cette structure du SQL a des comportements particulièrement contre-intuitifs, en particulier dès que des valeursnull
sont en jeu. -
N’utilisez pas
timestamp
(sans timezone) (même pour stocker des dates et heures UTC) : la gestion des données temporelles, c’est compliqué et ce type de champ a de très forts risques de faire autre chose que ce que vous imaginez. -
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.
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 wilk . É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 stopspam . Évalué à 3.
Petit moment nostalgie sur le "don't do this" et c'est parti en vrille au bureau :
la réf pour les vieux ou les trop jeunes : https://www.dailymotion.com/video/x7v5jl
# varchar(n)
Posté par stopspam . Évalué à 3.
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 :
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 SpaceFox (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 SpaceFox (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 Dring . É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 Dring . Évalué à 3.
Merde, trop long à modifier. L'histoire d'index, c'est pour char vs char(n).
[^] # Re: varchar(n)
Posté par SpaceFox (site web personnel, Mastodon) . Évalué à 4.
Pour moi il faut surtout comprendre que, dans le cas général, utiliser
varchar
plutôt quevarchar(n)
est préférable. D’ailleurs la règle est « Don't usevarchar(n)
by default » et pas « Don't usevarchar(n)
» ; et donc que sauf cas particuliers, une conception à base devarchar
outext
sans limites avec desvarchar(n)
là ou c’est nécessaire posera moins de problèmes (en général, pas seulement de performance) qu’une conception avec desvarchar(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 Olivier Jeannet . É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 SpaceFox (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 eMerzh (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 pas_pey . É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 ianux (site web personnel, Mastodon) . Évalué à 10.
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 georgeswwbush . É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.