mysql的count(*)的优化,获取千万级数据表的总行数

本文介绍了一种快速查询大数据表行数的方法,利用explain命令的rows参数代替count(*),极大提升了查询速度,适用于对行数精度要求不高的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

      这个问题是今天朋友提出来的,关于查询一个1200w的数据表的总行数,用count(*)的速度一直提不上去。找了很多优化方案,最后另辟蹊径,选择了用explain来获取总行数。

二、关于count的优化

      网上关于count()优化的有很多。博主这边的思路就是没索引的就建立索引关系,然后使用count(1)或者count(*)来提升速度。这两个函数默认使用的是数据表中最短的那个索引字段。我朋友这边因为表中只有一个索引字段,所以使用count(1)count(*)没什么区别。

MySQL中聚合函数count的使用和性能优化

mysql count(*) 会选哪个索引?

大家可以参考这两个博客,都挺不错的。

三、使用explain获取行数

1、关于explain

      关于explain,使用mysql的都知道,这个函数是专门用于查看sql语句的执行效率的,网上可供参考的文章很多。
定义: explain 命令速度很快,因为 explain 用并不真正执行查询,而是查询优化器【估算】的行数。

      我们使用explain之后,会看到返回很多参数,其中:
rows:显示MySQL认为它执行查询时必须检查的行数。就是这个东西了,既然我们要获取的是数据表的行数,那么可以使用:

explain select * from table;

2、关于返回值

      以前博主也没注意过返回值的问题,都是直接通过phpmyadmin来查看sql的执行效率。这次因为要用到rows的值,所以就打印了一下,原来这个explain函数是会返回一个数组。这样我们就能通过这个数组获取到我们需求的rows

在这里插入图片描述

      这里直接获取这个值即可。速度极快。原来查询速度是2.33s,换成只用explain之后,速度仅为0008s,提升十分巨大。

朋友博客:https://www.happyrmb.com/index/article/show/id/69.html

end

====================== 2019/3/7日补充 =============================

      explain的rows结果算是一个大概的统计结果。而count统计的是比较准确的,如果要追求准确的条数,那就使用count查询最好,如果是要大概的结果,那可以使用explain的rows当做结果,正常来说,rows的数值会比count大一些,特别是加的有where条件的话,row的结果是大于Count的结果的。

例如:

举个网上的例子来说,假如有一个语句 select * from t where column_a = 1 and column_b = 2;
全表假设有100条记录,column_a字段有索引(非联合索引),column_b没有索引。
column_a = 1 的记录有20条, column_a = 1 and column_b = 2 的记录有5条。

      那么最终查询结果应该显示5条记录。 explain结果中的rows应该是20. 因为这20条记录mysql引擎必须逐行检查是否满足where条件。

关于explain不准确:

关于explain不准确的问题,可以参考国外的一篇文章:
https://www.percona.com/blog/2006/07/24/mysql-explain-limits-and-errors/

需要注意不能完全相信explain的结果,特别是在使用limit的时候,结果也许会错的很离谱。其次,explain的结果也有可能会走错,一般发生在子查询的时候比较多。参考下面博客:
MySQL执行计划显示与执行过程不符合一例

这里多谢笑看泥鳅小同学的指正和讨论!

end

<think>首先,用户的问题是:“我想理解SQL中COUNT(1)的含义和用法 请问SQL SELECT COUNT(1) 的作用和意义”。所以,我需要解释SQL中COUNT(1)的含义、用法、作用和意义。 参考提供的引用,这些是关于SQL COUNT函数的讨论: - 引用[2]:讨论了count(*)count(1)和count(column)的区别与用法。 - 引用[3]:比较了SELECT COUNT(1)和SELECT COUNT(*)的性能。 - 引用[4]:解释了在不同情况下count(*)count(1)的效率。 - 引用[5]:提到count(1)和count(*)通常返回相同结果,但性能取决于表结构。 关键点: - COUNT(1)是SQL中的聚合函数,用于统计行数。 - 它与COUNT(*)类似,通常返回表中的行数,忽略NULL值。 - 性能方面:如果没有主键,count(1)可能比count(*)快;如果有主键,count(主键)最快;在MySQL中,count(*)可能被优化。 - 用法:SELECT COUNT(1) FROM table_name; 这会返回表中的行数。 现在,根据系统级指令: - 所有行内数学表达式使用$...$格式。但在这个上下文中,没有数学表达式,所以可能不需要。 - 独立公式使用$$...$$并单独段。同样,这里可能不适用。 - LaTeX语法正确:确保任何数学部分正确。 - 使用中文回答:整个回答要用中文。 - 生相关问题:在回答末尾,添加相关问题。 - 引用标识:在引用的段落末尾添加引用标识,如[^1]。 回答结构: 1. 清晰解释COUNT(1)的含义和用法。 2. 说明作用和意义。 3. 讨论性能考虑。 4. 添加引用标识到引用部分。 5. 最后,生相关问题。 内容大纲: - 介绍COUNT函数:COUNT是SQL中用于计数的函数。 - COUNT(1)的含义:COUNT(1)中的“1”是一个常量表达式,意思是“每一行都有一个值1”,所以COUNT(1)统计所有行数,类似于COUNT(*)。 - 用法示例:SELECT COUNT(1) FROM employees; 这将返回employees表中的行数。 - 作用和意义:用于快速获取表中的记录数,常用于报告、分页等场景。 - 性能比较:参考引用,解释在不同数据库和表结构下,COUNT(1)与COUNT(*)的性能差异。 - 结:COUNT(1)是一个高效的行数统计方法,通常与COUNT(*)等价。 生相关问题: 基于主题,生相关问题,如: 1. COUNT(1)和COUNT(*)有什么区别? 2. 在SQL中如何优化COUNT查询的性能? 3. COUNT函数如何处理NULL值? 确保回答真实可靠:基于提供的引用和一般SQL知识。 最终回答结构: - 开头直接回答问题。 - 逐步解释。 - 添加引用标识。 - 结尾添加相关问题。</think>### SQL中COUNT(1)的含义和用法 在SQL中,`COUNT()`是一个聚合函数,用于统计表中的行数或某列中非NULL值的数量。`COUNT(1)`是`COUNT()`函数的一种变体,它通过一个常量值`1`来实现计数。下面我将逐步解释其含义、用法、作用和意义,确保内容清晰可靠。 #### 1. **COUNT(1)的含义** - `COUNT(1)`中的`1`是一个常量表达式(constant expression),它不代表实际列值,而是为每一行生一个虚拟值“1”。COUNT函数会统计所有行中这个虚拟值的数量,因此`COUNT(1)`本质上返回表中的行数,**忽略NULL值**(因为常量表达式永远不会为NULL)。 - 与`COUNT(*)`类似:`COUNT(*)`也统计所有行数,但它在语义上更直接(表示“所有行”)。而`COUNT(1)`通过一个固定值来计数,两者在大多数情况下返回相同结果,即表的记录数[^2][^5]。 - 数学表达:在SQL中,COUNT函数的行为可以表示为: $$ \text{COUNT}(expression) = \sum_{i=1}^{n} \begin{cases} 1 & \text{if } expression_i \text{ is not NULL} \\ 0 & \text{otherwise} \end{cases} $$ 对于`COUNT(1)`,由于`1`始终非NULL,因此它简化为$\text{COUNT}(1) = n$(其中$n$是行数)[^2][^5]。 #### 2. **COUNT(1)的用法** - 基本语法:`COUNT(1)`通常用于`SELECT`语句中,作为聚合函数。格式如下: ```sql SELECT COUNT(1) FROM table_name; ``` 这会返回`table_name`表中的行数。 - 示例场景: - 统计员工表中的记录数: ```sql SELECT COUNT(1) AS total_employees FROM employees; ``` 输出:如果`employees`表有100行,则返回`total_employees = 100`。 - 结合`WHERE`子句过滤行: ```sql SELECT COUNT(1) FROM orders WHERE status = 'shipped'; ``` 这仅统计状态为“shipped”的订单行数。 - 在子查询或分组中使用: ```sql SELECT department, COUNT(1) AS emp_count FROM employees GROUP BY department; ``` 这会按部门分组统计员工数[^1][^2]。 - 注意:`COUNT(1)`不会检查列值是否为NULL,因为它基于常量。如果需要统计某列的非NULL值,应使用`COUNT(column_name)`,例如`COUNT(salary)`只统计`salary`列非NULL的行[^2][^5]。 #### 3. **COUNT(1)的作用和意义** - **作用**: - 高效统计行数:`COUNT(1)`提供了一种快速获取记录数的方法,常用于数据报告、分页查询(如计算页数)或性能监控。 - 简化查询:在不需要检查具体列值时,它比`COUNT(column_name)`更简洁,避免了NULL值处理的复杂性。 - **意义**: - 性能优化:在数据库引擎中,`COUNT(1)`通常被优化为直接扫描索引或表的最小单元(如行指针),而非实际数据列。这使其在某些场景下比`COUNT(*)`或`COUNT(column_name)`更快,尤其是表无主键时[^3][^4][^5]。 - 语义清晰:它明确表示“统计所有行”,减少歧义。在SQL标准中,`COUNT(1)`与`COUNT(*)`在功能上等价,但不同数据库可能对内部实现有细微优化(如MySQL的`COUNT(*)`优化)[^4][^5]。 - 适用场景:适用于表结构复杂或需要高并发计数的环境,例如在大型OLTP系统中快速获取元数据[^3][^4]。 #### 4. **性能考虑** - 与`COUNT(*)`和`COUNT(column_name)`的比较: - **无主键表**:`COUNT(1)`通常比`COUNT(*)`略快,因为它避免解析所有列;但`COUNT(主键)`如果有主键则最快(利用索引)[^3][^4][^5]。 - **有主键表**:`COUNT(主键列)`效率最高(例如`COUNT(id)`),因为可以直接使用索引扫描;`COUNT(1)`次之,`COUNT(*)`可能稍慢(但现代数据库如MySQL优化`COUNT(*)`)[^4][^5]。 - **通用规则**:在大多数数据库(如SQL Server、MySQL)中,`COUNT(1)`和`COUNT(*)`的性能差异极小,实际选择应基于可读性。测试表明,在千万级数据表上,差异通常小于1%[^3][^5]。 - 优化建议: - 使用覆盖索引(covering index)加速`COUNT(1)`查询。 - 避免在频繁更新的表上使用`COUNT(1)`,以免锁表影响性能[^3][^4]。 之,`SELECT COUNT(1)`在SQL中用于高效统计表行数,其核心意义是提供一个轻量级、可靠的计数方式。实际开发中,它和`COUNT(*)`可互换,但性能优化需根据表结构(如主键存在性)调整[^2][^3][^4][^5]。
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁柱同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值