标签:COUNT 函数 expr 数据库 查询 索引 行数 NULL
COUNT(expr) 函数使用总共分为三种情况:
名称 | 执行过程 |
---|---|
COUNT(*) | 在执行时返回检索到的行数计数,不管这些行是否包含 NULL 值 |
COUNT(1) | 在执行时遇到了行的时候为恒真表达式,在统计结果时和 COUNT(*) 一样统计所有行 |
COUNT(字段) | 在执行时全表扫描该字段,然后判断拿到的字段的值是不是为 NULL,不为 NULL 则累加 |
总结:
- COUNT(1) 和 COUNT(*) 表示的是直接查询符合条件的数据库表的行数
- COUNT(字段)表示的是查询符合条件的列的值,并判断不为NULL的行数的累计,效率会低
- 除了查询得到结果集有区别之外,相比COUNT(1) 和 COUNT(字段)来讲,COUNT(*)是 SQL92 定义的标准统计数的语法,是官方提供的标准方案,基于此,MySQL数据库对他进行过很多优化
注:
SQL92
是数据库的一个 ANSI/ISO 标准。它定义了一种语言(SQL)以及数据库的行为(事务、隔离级别等)
使用建议:
- 从效率层面说
COUNT(*) ≈ COUNT(1) > COUNT(字段)
- 因为 COUNT(*) 是 SQL92 定义的标准统计数的语法,所以推荐使用 COUNT(*)
- 判断数据在否,可使用
SELECT COUNT(*) FROM ...... LIMT 1
代替SELECT COUNT(*) ......
注:规避了 SQL 使用 COUNT 表达式扫表的操作,而是改用
SELECT 1 ... LIMIT 1
,数据库查询时遇到一条就返回,不会再继续查找和执行,如果存在传输回一条结果为 1 的数据 ,否则为 NULL,业务代码中直接判断是否非空即可
拓展:MySQL 数据库对 COUNT(*) 做了哪些优化
- MyISAM | 不支持事务,MyISAM中的锁是表级锁
因为MyISAM的锁是表级锁,所以同一张表上面的操作是串行执行的,MyISAM把表的总行数单独记录下来,如果只是使用COUNT(*)对表进行查询的时候,可以直接返回这个记录的数值就可以了。 - InnoDB | 支持事务,其中大部分操作都是行级锁
因为表的行数可能会被并发修改,缓存记录下来的总行数就不准确了。
在InnoDB中,使用 COUNT(*) 查询行数的时候,不需要进行扫表,只要获取记录行数而已。所以官方在针对 InnoDB 的SELECT COUNT(*) FROM
语句执行过程,会自动选择一个成本较低的索引进行的话,这样就可以大大节省时间。
InnoDB 中索引分为聚簇索引(主键索引)
和非聚簇索引(非主键索引)
,聚簇索引的叶子节点中保存的是整行记录,而非聚簇索引的叶子节点中保存的是该行记录的主键的值,非聚簇索引要比聚簇索引小很多,MySQL 会优先选择最小的非聚簇索引来扫表,这样可以保证 COUNT(*) 的最优效率。当查询语句中包含 WHERE 以及 GROUP BY 条件,会有一些其他的因素影响,所以要综合考虑。
标签:COUNT,函数,expr,数据库,查询,索引,行数,NULL 来源: https://blog.csdn.net/OldHavey/article/details/114625329
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。