Les colonnes non pertinentes affectent-elles le temps de requête des instructions sélectionnées?

10

Je suis juste curieux.

Supposons que vous ayez un tableau de 1 million d'enregistrements / lignes.

select order_value from store.orders

Cela fait-il une différence si cette table a 1 champ, 2 champs ou 100 champs, en temps réel de requête? Je veux dire tous les champs autres que "order_value".

En ce moment, je pousse des données vers un entrepôt de données. Parfois, je vide des champs dans la table qui "pourraient être utilisés à l'avenir, un jour" - mais ils ne sont pas interrogés pour le moment, par quoi que ce soit. Ces champs «étrangers» affecteraient-ils des instructions sélectionnées qui ne les incluent pas, directement ou indirectement (non * je veux dire)?

user45867
la source
Il existe des tonnes d'informations à ce sujet sur le Web. La clé est d'obtenir les informations les plus récentes à mesure que la technologie évolue. Ce que vous demandez dépend tellement de votre configuration particulière qu'il n'est pas possible de donner une très bonne réponse. Un point clé à retenir est que lorsque nous passons au SSD, de nombreuses choses qui étaient autrefois très importantes pour les performances ne sont plus le cas.
Joe

Réponses:

10

Cela dépend vraiment des index et des types de données.

En utilisant la base de données Stack Overflow comme exemple, voici à quoi ressemble la table Users:

DES NOISETTES

Il a un PK / CX sur la colonne Id. Il s'agit donc de l'intégralité des données de la table triées par Id.

Avec cela comme seul index, SQL doit lire tout cela (sans les colonnes LOB) en mémoire s'il n'est pas déjà là.

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SET STATISTICS TIME, IO ON 

SELECT u.Id
INTO  #crap1
FROM dbo.Users AS u

Le temps des statistiques et le profil io ressemblent à ceci:

Table 'Users'. Scan count 7, logical reads 80846, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2406 ms,  elapsed time = 446 ms.

Si j'ajoute un index non cluster supplémentaire sur juste l'ID

CREATE INDEX ix_whatever ON dbo.Users (Id)

J'ai maintenant un index beaucoup plus petit qui satisfait ma requête.

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SELECT u.Id
INTO  #crap2
FROM dbo.Users AS u

Le profil ici:

Table 'Users'. Scan count 7, logical reads 6587, physical reads 0, read-ahead reads 6549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2344 ms,  elapsed time = 384 ms.

Nous pouvons faire beaucoup moins de lectures et gagner un peu de temps CPU.

Sans plus d'informations sur la définition de votre table, je ne peux pas vraiment essayer de reproduire ce que vous essayez de mieux mesurer.

Mais vous dites qu'à moins qu'il n'y ait un index spécifique sur cette seule colonne, les autres colonnes / champs seront également analysés? S'agit-il simplement d'un inconvénient inhérent à la conception des tables de Rowstore? Pourquoi les champs non pertinents seraient-ils analysés?

Oui, cela est spécifique aux tables rowstore. Les données sont stockées par la ligne sur les pages de données. Même si d'autres données de la page ne sont pas pertinentes pour votre requête, cette ligne entière> page> index doit être lue en mémoire. Je ne dirais pas que les autres colonnes sont "scannées" autant que les pages sur lesquelles elles existent sont scannées pour récupérer la valeur unique sur celles-ci en rapport avec la requête.

En utilisant l'exemple de l'annuaire téléphonique: même si vous ne faites que lire des numéros de téléphone, lorsque vous tournez la page, vous tournez le nom, le prénom, l'adresse, etc. avec le numéro de téléphone.

Erik Darling
la source
@ jpmc26 Cela peut être pire que cela, car si les colonnes demandées font toutes partie d'un index, la requête peut être servie simplement en regardant l'index. Si les colonnes ne sont pas indexées, elles peuvent entraîner le chargement de l'enregistrement principal et même des enregistrements secondaires pour les types de table / colonne non groupés.
Christopher Schultz
12

Cela dépend de la structure de la table et des index disponibles.

  • Cas A: table commune (magasin de lignes), aucun index activé (order_value).

    Le seul plan d'exécution possible est de lire l'intégralité du tableau (ce qui est bien sûr très différent quand il fait 2 vs 200 colonnes, donc quelques vs quelques milliers d'octets de large).

  • Cas B: table commune, il existe un index sur (order_value)ou certains autres index qui incluent cette colonne.

    Il y a un meilleur plan maintenant, scannez tout l'index (l'un d'eux) - qui est bien sûr beaucoup plus étroit que la table entière, juste quelques octets. Ce qui n'est pas pertinent si le tableau comporte 2 ou 200 colonnes. Seul l'index est analysé.

  • Cas C: c'est une table columnstore.

    Comme son nom l'indique, la structure de ces tables est orientée colonne par colonne, et non par ligne. Aucun index n'est nécessaire, la conception de la table elle-même est adaptée à la lecture de colonnes entières.

ypercubeᵀᴹ
la source
Ma connaissance est un peu verte sur cette question. Il est plus classique (par exemple, une base de données SQL Server typique) d'avoir des tables de lignes de données, n'est-ce pas? Pourquoi la table entière serait-elle analysée si une seule colonne / zone devait être retournée? Est-ce juste inhérent à la conception des tables de Rowstore?
user45867
@ user45867 oui, les données sont stockées dans des lignes (à l'exception de très grandes colonnes qui sont stockées à l'extérieur). Lorsque SQL Server lit à partir du disque, il lit en blocs entiers, il ne peut pas lire uniquement la partie qui a une colonne.
ypercubeᵀᴹ