J'ai un BookChapters de table SQL avec plus de 20 millions de lignes. Il a une key primaire en cluster (bookChapterID) et n'a pas d'autres keys ou index. Il prend des milisecondes pour exécuter la requête suivante
if (select count(*) from BookChapters) = 0 ...
Cependant, il faut plus de 10 minutes quand je le change comme ça
if (select count(*) from BookChapters) = 1 ...
ou
if (select count(*) from BookChapters) > 1 ...
Pourquoi donc? Comment puis-je get le select count(*)
pour exécuter plus vite?
Mikael Eriksson a une bonne explication ci-dessous pourquoi la première requête est rapide:
Le server SQL l'optimise en: if exists(select * from BookChapters)
. Donc, il va chercher la présence d'une ligne au lieu de countr toutes les lignes dans la table.
Pour les deux autres requêtes, SQL Server utiliserait la règle suivante. Pour effectuer une requête comme SELECT COUNT(*)
, SQL Server utilisera l'index non cluster le plus étroit pour countr les lignes. Si la table n'a aucun index non cluster, elle doit parsingr la table.
En outre, si votre table a un index clusterisé , vous pouvez get votre count encore plus rapidement en utilisant la requête suivante (empruntée à ce site Get Row Counts Fast! )
--SQL Server 2005/2008 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 --SQL Server 2000 SELECT OBJECT_NAME(i.id) [Table_Name], i.rows [Row_Count] FROM sysindexes i (NOLOCK) WHERE i.indid in (0,1) ORDER BY i.rows desc
Il utilise la table système sysindexes. Plus d'informations vous pouvez find ici SQL Server 2000 , SQL Server 2005 , SQL Server 2008 , SQL Server 2012
Voici un autre lien Pourquoi mon SELECT COUNT (*) est-il si lent? avec une autre solution. Il montre la technique que Microsoft utilise pour afficher rapidement le nombre de lignes lorsque vous faites un clic droit sur la table et select les propriétés.
select sum (spart.rows) from sys.partitions spart where spart.object_id = object_id('YourTable') and spart.index_id < 2
Vous devriez constater que cela revient très rapidement, peu importe le nombre de tables que vous avez.
Si vous utilisez encore SQL 2000, vous pouvez utiliser la table sysindexes pour get le numéro.
select max(ROWS) from sysindexes where id = object_id('YourTable')
Ce nombre peut être légèrement différent selon la fréquence à laquelle SQL met à jour la table sysindexes, mais il est généralement correct (ou du less assez proche).
essayez ceci si vous voulez seulement connaître les lignes:
exec sp_spaceused [TABLE_NAME]
Si vous regardez les plans d'exécution de vos requêtes, vous verrez ce qui se passe.
Votre première requête if (select count(*) from BookChapters) = 0
est reconnue par l'optimiseur de requête comme if exists(select * from BookChapters)
. SQL Server sait que l'expression est vraie s'il y a au less une ligne présente, donc il cherche la présence d'une ligne au lieu de countr toutes les lignes de la table.
Pour vos autres requêtes, il ne peut pas être aussi intelligent et doit countr le nombre de lignes dans la table avant de pouvoir décider si l'expression vaut true ou false.
Avez-vous considéré le select count(BookChapterId) from BookChapterTable
requêtes select count(BookChapterId) from BookChapterTable
? – où BookChapterId est un index non cluster . Cela devrait le faire courir beaucoup plus vite.
Selon la façon dont la table est utilisée et les lignes accédées, l'interrogation par rapport à l'index non clusterisé pourrait être le point key: je viens de prendre quelques points à MDSN:
essayez ceci, si vous avez besoin de détecter, si la table a plus de lignes qu'une:
if (SELECT COUNT(*) FROM (SELECT TOP 2 * FROM BookChapters) AS b) > 1