2
votes

Une requête SELECT COUNT (*) doit-elle effectuer une analyse complète de la table?

Une requête qui obtient le nombre de toutes les lignes d'une table doit-elle effectuer une analyse complète de la table ou SQL Server gère-t-il un nombre de lignes quelque part?

CREATE TABLE TABLE_NAME
(
  Id int PRIMARY KEY IDENTITY(1, 1),
  Name nvarchar(50) NOT NULL
);

La table TABLE_NAME a une clé primaire, et donc un index clusterisé, et ressemble à ceci:

SELECT COUNT(*) FROM TABLE_NAME;

J'utilise Microsoft SQL Server 2014.

p>


3 commentaires

La table a-t-elle une clé primaire?


non, il recherchera chaque ligne de la table, le serveur sql ne maintiendra pas de compteur


Le serveur gère un nombre de lignes ailleurs , dans sys.partitions . La requête que vous avez écrite ne l'utilisera cependant pas. L'optimiseur de requêtes peut décider d'utiliser une analyse de table ou d'analyser un index


4 Réponses :


4
votes

Lorsque SQL Server exécute une requête telle que SELECT COUNT (*) , SQL Server utilise l ' index non clusterisé le plus étroit pour compter les lignes. Si la table ne possède aucun index non clusterisé , elle devra scanner la table.

Si votre table a un index clusterisé , vous pouvez obtenir votre décompte encore plus rapidement.


3 commentaires

Donc, si la table a une clé primaire et donc un index clusterisé, SQL Server effectue-t-il une analyse complète de la table ou non? Comment obtient-il alors le nombre de lignes?


Si la table a une clé primaire, elle n'effectuera pas l'analyse complète de la table. Pour votre référence dbatipster.blogspot.com/2009/08/get -row-count-fast.html


@ WaterCoolerv2 Non - ne supposez pas que la clé primaire et l'index clusterisé sont toujours les mêmes.



1
votes
SELECT COUNT(*) FROM TABLE_NAME;
Does a full table scan.For optimizations you can refer to this.

0 commentaires

0
votes

vous pouvez suivre la voie. il est meilleur en performances, je suppose.

SELECT COUNT(1) FROM TABLE_NAME 


2 commentaires

Mythe - vous obtiendrez exactement le même plan de requête.


Je pourrais voir la différence dans le temps de sortie de la requête si je choisis count (*) et count (1)



5
votes

Le serveur lira toujours tous les enregistrements (s'il y a un index, il analysera l'index entier) pour compter les lignes. Vous ne pouvez pas y échapper tant que vous faites SELECT COUNT (*) FROM Table .

Si votre table a un index clusterisé, vous pouvez remplacez votre requête par une requête" sous le capot "pour récupérer le décompte sans récupérer les enregistrements avec:

SELECT 
    TableName = t.NAME,
    SchemaName = s.Name,
    [RowCount] = p.rows,
    TotalSpaceMB = CONVERT(DECIMAL(18,2), SUM(a.total_pages) * 8 / 1024.0), 
    UsedSpaceMB = CONVERT(DECIMAL(18,2), SUM(a.used_pages) * 8 / 1024.0),
    UnusedSpaceMB = CONVERT(DECIMAL(18,2), (SUM(a.total_pages) - SUM(a.used_pages)) * 8 / 1024.0)
FROM 
    sys.tables t
    INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
    INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
    INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
    LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, 
    s.Name, 
    p.Rows
ORDER BY 
    TotalSpaceMB DESC

si vous recherchez un décompte approximatif des enregistrements, vous pouvez également utiliser la requête suivante:

SELECT OBJECT_NAME(i.id) [Table_Name], i.rowcnt [Row_Count]
FROM sys.sysindexes i WITH (NOLOCK)
WHERE i.indid in (0,1)
ORDER BY i.rowcnt desc

Cela affichera les tables non système avec leur nombre de lignes calculé (pas exact) et la somme des tailles de leurs données (avec tout index qu'elles pourraient avoir), relativement rapidement sans récupérer les enregistrements.


0 commentaires