Nombre de SQL (*)

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:

    • Avant de créer des index non cluster, comprenez comment vos données seront accessibles. Envisagez d'utiliser des index non clusterisés pour:
    • Colonnes contenant un grand nombre de valeurs distinctes, telles qu'un
      combinaison du nom et du prénom (si un index clusterisé est utilisé pour d'autres colonnes). S'il y a très peu de valeurs distinctes, telles que
      seulement 1 et 0, la plupart des requêtes n'utiliseront pas l'index car une table
      L'parsing est généralement plus efficace.
    • Les requêtes qui ne renvoient pas de grands sets de résultats.
    • Colonnes fréquemment impliquées dans les conditions de search d'une requête (WHERE
      clause) qui returnne des correspondances exactes.
    • Applications du système d'aide à la décision pour lesquelles les jointures et le regroupement sont fréquemment requirejs. Créez plusieurs index non clusterisés sur les colonnes impliquées dans les opérations de jointure et de regroupement, ainsi qu'un index clusterisé sur les colonnes de foreign keys.
    • Couvrant toutes les colonnes d'une table dans une requête donnée. Cela élimine complètement l'access à la table ou à l'index clusterisé.

    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