欢迎来到.net学习网

欢迎联系站长一起更新本网站!QQ:879621940

您当前所在位置:首页 » Sql随手笔记 » 正文

关于sql中count写法的探讨

创建时间:2013年12月23日 14:27  阅读次数:(6835)
分享到:
我们在查询表中数据的数量时,有人喜欢用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
来源:http://bbs.csdn.net/topics/390635419
说明:所有来源为 .net学习网的文章均为原创,如有转载,请在转载处标注本页地址,谢谢!
【编辑:Wyf

打赏

取消

感谢您的支持,我会做的更好!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

最新评论

共有评论0条
  • 暂无任何评论,请留下您对本文章的看法,共同参入讨论!
发表评论:
留言人:
内  容:
请输入问题 43+16=? 的结果(结果是:59)
结  果: