Beaucoup de colonnes vs peu de tables - en termes de performances


12

Oui, je suis conscient que la normalisation des données devrait être ma priorité (telle quelle).

  1. J'ai une table avec 65 colonnes stockant des données du véhicule avec des colonnes: used_vehicle, color, doors, mileage,price et ainsi de suite, en 65 au total.
  2. Maintenant, je peux diviser cela et avoir une Vehicletable, VehicleInterior, VehicleExterior, VehicleTechnical, VehicleExtra(tous les un à un avec les principaux Vehicletableau).

Supposons que j'aurai environ 5 millions de lignes (véhicules).

On SELECTavec une WHEREclause: les performances seront-elles mieux recherchées (les deux cas indexés au moins surIDs ):

  1. Vehicle table avec 65 colonnes ou
  2. Vehicletable avec JOINSsur quatre autres tables (toutes avec 5 millions de lignes) pour retourner toutes les données liées à Vehicle?

(Selon le moteur de base de données, pensez à PostgreSQL et / ou MySQL).

Vous appréciez vraiment les informations détaillées que vous pourriez avoir de votre expérience précédente?


1
L' une des raisons faire (partitionnement vertical) est de savoir si vous avez des questions qui traitent avec les colonnes de VehicleInterior, d' autres requêtes qui traitent avec des colonnes de seulement VehicleTechnical, etc. Ou s'il y a beaucoup de lignes / véhicules qui ne sont absolument pas d' info au sujet (par exemple) VehicleExtrasi au lieu de plusieurs lignes avec beaucoup de valeurs nulles dans la même table, vous avez des lignes dans le reste des tables et aucune ligne dansVehicleExtra
ypercubeᵀᴹ

Réponses:


14

En supposant que nous parlons de relations 1: 1 entre toutes les tables.

Le stockage global est pratiquement toujours (substantiellement) moins cher avec une seule table au lieu de plusieurs tables dans une relation 1: 1. Chaque ligne a 28 octets de surcharge, plus généralement quelques octets supplémentaires pour un remplissage supplémentaire. Et vous devez stocker la colonne PK avec chaque table. Et avoir un index séparé (redondant) sur chacune de ces colonnes ... La taille est importante pour les performances.

Cela est même vrai si de nombreuses colonnes sont NULL dans la plupart des lignes car le stockage NULL est très bon marché :

Lors de la récupération de toutes les colonnes, une seule table est sensiblement plus rapide que 5 tables réunies. C'est aussi beaucoup plus simple . Cinq tables peuvent être difficiles à joindre si toutes les lignes ne sont pas présentes dans toutes les tables. Avec des WHEREconditions ciblant une seule table, il est assez facile d'ajouter d'autres tables avec LEFT JOIN. Pas aussi banal si vous avez des prédicats sur plusieurs tables ...

Le partitionnement vertical peut encore améliorer les performances de certaines requêtes. Par exemple, si 90% de vos requêtes récupèrent les mêmes 5 colonnes sur les 65 disponibles, ce serait plus rapide avec une table contenant uniquement ces 5 colonnes.

OTOH, vous pourriez être en mesure de répondre à de telles requêtes sur quelques colonnes sélectionnées avec un index «couvrant» permettant des analyses d'index uniquement .

Un autre candidat pour le partitionnement vertical: si vous avez beaucoup de mises à jour sur seulement quelques colonnes, alors que le reste ne change presque jamais. Dans un tel cas, il pourrait être considérablement moins coûteux de diviser des lignes, car Postgres écrit une nouvelle version de ligne pour chaque mise à jour. Il existe des exceptions pour les grandes valeurs stockées hors ligne ("TOASTed"). Plus de détails:

Cela dépend vraiment de la situation complète. En cas de doute, optez pour la solution simple d'avoir une seule table, surtout si elle représente bien la réalité: dans votre exemple, ce sont tous des attributs d'une voiture et ont du sens ensemble.


les mises à jour seront rares si aucune et les sélections seront principalement pour toutes les colonnes (page de détails du véhicule) et les informations principales (quelques colonnes) pour la liste des résultats de la recherche, et en fait, la meilleure solution serait peut-être deux tableaux: un avec les informations principales (quelques colonnes) ) et l'autre table avec le reste des colonnes. dans ce cas, quelle est votre opinion sur sql rejoint avec disons 5 millions de lignes - en termes de performances? BTW merci pour votre effort détaillé
Urim Kurtishi

1
@octavius: Une seule table avec un index multicolonne sur les quelques colonnes pour permettre des analyses d'index uniquement pour la liste des résultats pourrait être la meilleure route. (Sachez que la séquence de colonnes est importante dans les index btree .) Les jointures ne sont pas si chères, mais elles seront toujours plus rapides sans jointure. La taille de stockage supplémentaire et la répartition des données pour plusieurs tables peuvent être le ralentissement le plus important (plus de pages de données à lire pour chaque requête).
Erwin Brandstetter

1
Je suis d'accord avec le commentaire d'Erwins que la réponse dépendra vraiment de la situation complète ou de l'utilisation du monde réel. Si vous avez constaté que 90% des requêtes se trouvaient sur un petit sous-ensemble de données et que les performances étaient absolument primordiales, il pourrait y avoir lieu de justifier l'effort supplémentaire divisé en plusieurs tables. Personnellement, j'essaierais de garder le modèle de données simple. Aussi, à quelle vitesse est assez rapide? Combien d'efforts faites-vous pour sauver cette dernière milliseconde? Avez-vous essayé de simuler des données et de faire des tests?
Sir Swears-a-lot

@ErwinBrandstetter, vous avez mentionné dans votre réponse que la relation est de 1: 1. Qu'en est-il des navires de relation 1: N?
Slim

Pour une relation 1: N, vous avez quand même besoin de deux tables distinctes. Sauf si vous recadrez plusieurs lignes dans un tableau ou un type de document. Alors ça dépend. Les principes décrits ici s'appliquent indépendamment. Vos modèles d'accès et stratégies d'indexation peuvent faire la différence. Posez une nouvelle question si vous souhaitez être plus précis.
Erwin Brandstetter

0

Une sélection sur une seule table devrait toujours être plus rapide. Dès que vous avez trouvé votre véhicule, vous avez déjà tous les détails.

Cependant, vous perdez l'efficacité de la normalisation. Par exemple, si 1 voiture avait de nombreux modèles avec différentes options.

Est-ce un db de référence de toutes les voitures? Ou une liste de véhicules d'occasion? Y aurait-il de nombreux exemples de la même marque / modèle avec les mêmes options?

Edit: je devrais qualifier ma réponse comme étant des rdbms génériques plutôt que des postgres spécifiques. Je m'en remets à la réponse détaillée de @ Erwin spécifique aux postgres


2
"Une sélection sur une seule table devrait toujours être plus rapide." Pourquoi?
ypercubeᵀᴹ

vehiclemake et vehiclemodel sont des tables différentes, donc la table de véhicule a des clés étrangères de vehiclemake et vehiclemodel. je ne pense pas que la normalisation soit un problème ici. je comprends que sélectionner sur une seule table serait plus rapide, mais nous avons une situation différente, comment la ligne avec de nombreuses colonnes affectera-t-elle les performances et ainsi de suite par rapport aux tables avec moins de colonnes (mais peu de tables - 5 d'entre elles avec des jointures)
Urim Kurtishi

Désolé d'avoir raté le point que la marque et le modèle étaient déjà séparés. La version courte est que les jointures nécessitent un effort pour le moteur de base de données. Si vous utilisez une seule table / ligne, vous obtiendrez tout en une seule sélection, ce qui entraînerait moins d'E / S et de surcharge pour le moteur de base de données.
Sir Swears-a-lot
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.