我们在查询表中数据的数量时,有人喜欢用count(*),有人用count(1),还有些朋友会用count(主键),但这几种用法那种会更优一些呢?下面在csdn上面看到的一篇文章,摘抄如下:
关于COUNT的写法,大致有以下几种:
COUNT(*)
COUNT(1)
COUNT(主键)
COUNT(列名)
我还是写个小例子:
USE TEMPDB
GO
IF OBJECT_ID('TB') IS NOT NULL DROP TABLE TB
GO
CREATE TABLE TB(COL1 INT,COL2 INT,COL3 INT,COL4 INT)
GO
CREATE CLUSTERED INDEX INX_TB_COL1_COL2 ON TB(COL1,COL2)
GO
CREATE INDEX INX_TB_COL3 ON TB(COL3)
GO
INSERT INTO TB
SELECT T1.number,T2.number,CASE WHEN T1.number%3=0 THEN NULL ELSE T1.number END,T1.NUMBER+T2.number
FROM MASTER..spt_values T1
INNER JOIN MASTER..spt_values T2 ON T1.number=T2.number-1
GO
SELECT COUNT(*)
FROM TB
SELECT COUNT(1)
FROM TB
SELECT COUNT(COL1)
FROM TB
SELECT COUNT(COL2)
FROM TB
SELECT COUNT(COL3)
FROM TB
SELECT COUNT(COL4)
FROM TB
SELECT COUNT(DISTINCT COL3)
FROM TB
SELECT COUNT(1),
COUNT(COL3),
COUNT(DISTINCT COL3),
COUNT(COL4),
COUNT(DISTINCT COL4)
FROM TB
自己逐个运行SELECT看执行计划,你会发现前五个的执行计划看起来是一样的,都是走INX_TB_COL3,这是因为系统判断COL3的索引大小小于COL1+COL2的聚集索引,而且COL3中包含了前五个语句所需要的所有列。
但看到第一步的INDEX_SCAN中,会发现COUNT(*)和COUNT(1)是没有输出对象的,即假输出,只输出返回行数,不输出具体的列。而COUNT(COL1),COUNT(COL2),COUNT(COL3)都有一个
OutPutLIST,分别是这三列。这是因为系统要算这三列中有多少非NULL的值,而COUNT(*)和COUNT(1)都是有一行算一行,不管是不是NULL。
COUNT(COL4)走的是INX_TB_COL1_COL2,也就是聚集索引扫描了,因为COL3中只包含键列COL1、COL2和值列COL3,所以COUNT(COL4)无法走COL3,只能走聚集索引扫描,也就是全表扫描。
后面的COUNT(DISTINCT COL3)是为了让你们对比计划的,所谓DISTINCT,就是在输出了COL3再GROUP BY一下再计算行数。
最后一句是演示COUNT用法,无其它意义。
结论:
COUNT(1)和COUNT(*)是一样的,你可以在里面写任何常量,如COUNT('CSDNDSB'),不会输出一列常量,不会去系统表里找所有列名。
COUNT(1)和COUNT(列名)意义不同,不能放在一起比较。唯一可比较的情况是列名是单主键表的主键列,即聚集非空单键值索引,这种情况下除非想要强制走聚集索引扫描,否则COUNT(1)优于COUNT(列名),因为前者允许计划选择最估索引,而且没有列输出。俌W