Question assez simple, probablement répondu quelque part, mais je n'arrive pas à former la bonne question de recherche pour Google ...
Le nombre de colonnes dans une table particulière affecte-t-il les performances d'une requête, lors d'une requête sur un sous-ensemble de cette table?
Par exemple, si la table Foo a 20 colonnes, mais que ma requête ne sélectionne que 5 de ces colonnes, le fait d'avoir 20 colonnes (contre, disons, 10) affecte-t-il les performances de la requête? Supposons par souci de simplicité que tout élément de la clause WHERE soit inclus dans ces 5 colonnes.
Je suis préoccupé par l'utilisation du cache tampon de Postgres en plus du cache disque du système d'exploitation. J'ai très mal compris la conception du stockage physique de Postgres. Les tableaux sont stockés sur plusieurs pages (par défaut à 8 Ko en taille par page), mais je ne comprends pas très bien comment les tuples sont organisés à partir de là. PG est-il assez intelligent pour extraire uniquement du disque les données qui comprennent ces 5 colonnes?
la source
Réponses:
Le stockage physique des lignes est décrit dans les documents de la mise en page de la base de données . Le contenu de la colonne pour la même ligne est tous stockés dans la même page de disque, à l'exception notable du contenu éd de TOAST (trop grand pour tenir dans une page). Le contenu est extrait séquentiellement dans chaque ligne, comme expliqué:
Dans le cas le plus simple (pas de colonnes TOAST), postgres récupérera la ligne entière même si quelques colonnes sont nécessaires. Donc, dans ce cas, la réponse est oui, avoir plus de colonnes peut avoir un impact négatif clair sur le cache de tampon de gaspillage, en particulier si le contenu des colonnes est important tout en restant sous le seuil TOAST.
Maintenant, le cas TOAST: lorsqu'un champ individuel dépasse ~ 2 Ko, le moteur stocke le contenu du champ dans une table physique distincte. Il entre également en jeu lorsque la ligne entière ne tient pas dans une page (8 Ko par défaut): certains des champs sont déplacés vers le stockage TOAST. Doc dit:
Les contenus TOAST ne sont pas récupérés lorsqu'ils ne sont pas explicitement nécessaires, leur effet sur le nombre total de pages à récupérer est donc faible (quelques octets par colonne). Cela explique les résultats dans la réponse de @ dezso.
En ce qui concerne les écritures, chaque ligne avec toutes ses colonnes est entièrement réécrite à chaque MISE À JOUR, quelles que soient les colonnes modifiées. Donc, avoir plus de colonnes est évidemment plus coûteux pour les écritures.
la source
La réponse de Daniel se concentre sur le coût de lecture des lignes individuelles. Dans ce contexte: placer les
NOT NULL
colonnes de taille fixe en premier dans votre tableau aide un peu. Mettre les colonnes pertinentes en premier (celles que vous recherchez) aide un peu. La minimisation du remplissage (en raison de l'alignement des données) en jouant à l'alignement tetris avec vos colonnes peut vous aider un peu. Mais l'effet le plus important n'a pas encore été mentionné, en particulier pour les grandes tables.Des colonnes supplémentaires font évidemment qu'une ligne couvre plus d'espace disque, de sorte que moins de lignes tiennent sur une seule page de données (8 Ko par défaut). Les lignes individuelles sont réparties sur plusieurs pages. Le moteur de base de données doit généralement récupérer des pages entières, pas des lignes individuelles . Peu importe que les lignes individuelles soient un peu plus petites ou plus grandes - tant que le même nombre de pages doit être lu.
Si une requête récupère une portion (relativement) petite d'une grande table, où les lignes sont réparties de manière plus ou moins aléatoire sur l'ensemble de la table, prises en charge par un index, cela se traduira par environ le même nombre de lectures de page, sans trop de considération à la taille de ligne. Les colonnes non pertinentes ne vous ralentiront pas beaucoup dans un cas (rare).
En règle générale, vous récupérerez des correctifs ou des groupes de lignes qui ont été saisis dans l'ordre ou la proximité et partagerez des pages de données. Ces lignes sont réparties en raison de l'encombrement, davantage de pages de disque doivent être lues pour satisfaire votre requête. Devoir lire plus de pages est généralement la raison la plus importante pour laquelle une requête est plus lente. Et c'est le facteur le plus important pour lequel les colonnes non pertinentes ralentissent vos requêtes.
Avec les grandes bases de données, il n'y a généralement pas assez de RAM pour tout garder en mémoire cache. De plus grandes lignes occupent plus de cache, plus de conflits, moins de hits de cache, plus d'E / S de disque. Et les lectures sur disque sont généralement beaucoup plus chères. Moins avec les SSD, mais une différence substantielle demeure. Cela ajoute au point ci-dessus sur les lectures de page.
Il peut ou non être important que les colonnes non pertinentes soient éditées TOAST. Les colonnes pertinentes peuvent également être éditées TOAST, ramenant en grande partie le même effet.
la source
Un petit test:
Limiter la requête aux 250 premières lignes (
WHERE num <= 250
) donne respectivement 34,539 ms et 8,343 ms. La sélection de tout sauflong_long_text
de cet ensemble limité donne 18,432 ms. Cela montre que, selon vos termes, PG est assez intelligent.la source