我们知道,MySQL 一直依赖对 count(*) 的执行很头疼。很早的时候,MyISAM 引擎自带计数器,可以秒回;不过 InnoDB 就需要实时计算,所以很头疼。以前有多方法可以变相解决此类问题,比如:

1. 模拟 MyISAM 的计数器比如表 ytt1,要获得总数,我们建立两个触发器分别对 insert/delete 来做记录到表 ytt1_count,这样只需要查询表 ytt1_count 就能拿到总数。ytt1_count 这张表足够小,可以长期固化到内存里。不过缺点就是有多余的触发器针对 ytt1 的每行操作,写性能降低。这里需要权衡。

2. 用 MySQL 自带的 sql_calc_found_rows 特性来隐式计算

依然是表 ytt1,不过每次查询的时候用 sql_calc_found_rows 和 found_rows() 来获取总数,比如:mysql>select sql_calc_found_rows * from ytt1 where 1  order by id desc limit 1;

+------+------+

| id   | r1   |

+------+------+

| 3072 |   73 |

+------+------+

1 row in set, 1 warning (0.00 sec)

mysql> show warnings;

+---------+------+-------------------------------------------------------------------------------------------------------------------------+

| Level   | Code | Message                                                                                                                 |

+---------+------+-------------------------------------------------------------------------------------------------------------------------+

| Warning | 1287 | SQL_CALC_FOUND_ROWS is deprecated and will be removed in a future release. Consider using two separate queries instead. |

+---------+------+-------------------------------------------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select found_rows() as 'count(*)';

+----------+

| count(*) |

+----------+

|     3072 |

+----------+

1 row in set, 1 warning (0.00 sec)

这样的好处是写法简单,用的是 MySQL 自己的语法。缺点也有,大概有两点:1. sql_calc_found_rows 是全表扫。2. found_rows() 函数是语句级别的存储,有很大的不确定性,所以在 MySQL 主从架构里,语句级别的行级格式下,从机数据可能会不准确。不过行记录格式改为 ROW 就 OK。所以最大的缺点还是第一点。

从 warnings 信息看,这种是 MySQL 8.0 之后要淘汰的语法。

3. 从数据字典里面拿出来粗略的值mysql> select table_rows from information_schema.tables where table_name = 'ytt1';    +------------+    | TABLE_ROWS |    +------------+    |       3072 |    +------------+    1 row in set (0.12 sec)

那这样的适合新闻展示,比如行数非常多,每页显示几行,一般后面的很多大家也都不怎么去看。缺点是数据不是精确值。

4. 根据表结构特性特殊的取值

这里假设表 ytt1 的主键是连续的,并且没有间隙,那么可以直接mysql> select max(id) as cnt from ytt1;    +------+    | cnt  |    +------+    | 3072 |    +------+    1 row in set (0.00 sec)

不过这种对表的数据要求比较高。

5. 标准推荐取法(MySQL 8.0.17 建议)

MySQL 8.0 建议用常规的写法来实现。mysql>select * from ytt1 where 1 limit 1;

+----+------+

| id | r1   |

+----+------+

| 87 |    1 |

+----+------+

1 row in set (0.00 sec)

mysql> select count(*) from ytt1;

+----------+

| count(*) |

+----------+

|     3072 |

+----------+

1 row in set (0.01 sec)

第五种写法是 MySQL 8.0.17 推荐的,也就是说以后大部分场景直接实时计算就 OK 了。MySQL 8.0.17 以及在未来的版本都取消了sql_calc_found_rows 特性,可以查看第二种方法里的 warnings 信息。相比 MySQL 5.7,8.0 对 count(*) 做了优化,没有必要在用第二种写法了。我们来看看 8.0 比 5.7 在此类查询是否真的有优化?MySQL 5.7mysql>select version();

+------------+

| version()  |

+------------+

| 5.7.27-log |

+------------+

1 row in set (0.00 sec)

mysql> explain format=json select count(*) from ytt1\G

*************************** 1. row ***************************

EXPLAIN: {

"query_block": {

"select_id": 1,

"cost_info": {

"query_cost": "622.40"

},

"table": {

"table_name": "ytt1",

"access_type": "index",

"key": "PRIMARY",

"used_key_parts": [

"id"

],

"key_length": "4",

"rows_examined_per_scan": 3072,

"rows_produced_per_join": 3072,

"filtered": "100.00",

"using_index": true,

"cost_info": {

"read_cost": "8.00",

"eval_cost": "614.40",

"prefix_cost": "622.40",

"data_read_per_join": "48K"

}

}

}

}

1 row in set, 1 warning (0.00 sec)

MySQL 8.0 下执行同样的查询mysql>select version();

+-----------+

| version() |

+-----------+

| 8.0.17    |

+-----------+

1 row in set (0.00 sec)

mysql> explain format=json select count(*) from ytt1\G

*************************** 1. row ***************************

EXPLAIN: {

"query_block": {

"select_id": 1,

"cost_info": {

"query_cost": "309.95"

},

"table": {

"table_name": "ytt1",

"access_type": "index",

"key": "PRIMARY",

"used_key_parts": [

"id"

],

"key_length": "4",

"rows_examined_per_scan": 3072,

"rows_produced_per_join": 3072,

"filtered": "100.00",

"using_index": true,

"cost_info": {

"read_cost": "2.75",

"eval_cost": "307.20",

"prefix_cost": "309.95",

"data_read_per_join": "48K"

}

}

}

}

1 row in set, 1 warning (0.00 sec)

从以上结果看出,第二个 SQL 性能(cost_info)相对第一个提升了一倍。

mysql 5.622_新特新解读 | MySQL 8.0 对 count(*)的优化相关推荐

  1. c语言 字符串 正序再倒序_新特性解读 | MySQL 8.0 索引特性3 -倒序索引

    原创作者:杨涛涛 我们今天来介绍下 MySQL 8.0 引入的新特性:倒序索引. MySQL长期以来对索引的建立只允许正向asc存储,就算建立了desc,也是忽略掉. 比如对于以下的查询,无法发挥索引 ...

  2. 中累计直方图_新特性解读 | MySQL 8.0 直方图

    原创作者:杨涛涛 MySQL 8.0 推出了histogram,也叫柱状图或者直方图.先来解释下什么叫直方图. 关于直方图 我们知道,在DB中,优化器负责将SQL转换为很多个不同的执行计划,完了从中选 ...

  3. 新特性解读 | MySQL 8.0 对 limit 的优化

    作者:杨奇龙 网名"北在南方",资深 DBA,主要负责数据库架构设计和运维平台开发工作,擅长数据库性能调优.故障诊断. 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不 ...

  4. mysql applier_新特性解读 | MySQL 8.0.18 有权限控制的复制

    背景 MySQL 8.0.18 以前,从服务器都是在不检查权限的情况下执行复制事务的,这样做是为了能够让主服务器获取所有内容.实际上,这意味着从机完全信任主机.但是,可能存在一些设置,其中更改跨越了主 ...

  5. 新特性解读 | MySQL 8.0 对 GTID 的限制解除

    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年.擅长 MySQL.PostgreSQL.MongoDB 等开源数据库相关的备份恢复.SQL 调优.监控运维.高可用架构设计等.目前任职于爱可生, ...

  6. 新特性解读 | MySQL 8.0 新密码策略(上)

    作者:杨涛涛 资深数据库专家,专研 MySQL 十余年.擅长 MySQL.PostgreSQL.MongoDB 等开源数据库相关的备份恢复.SQL 调优.监控运维.高可用架构设计等.目前任职于爱可生, ...

  7. concat 不是可以识别的 内置函数名称。_新特性解读 | MySQL 8.0 窗口函数详解

    背景 一直以来,MySQL 只有针对聚合函数的汇总类功能,比如MAX, AVG 等,没有从 SQL 层针对聚合类每组展开处理的功能.不过 MySQL 开放了 UDF 接口,可以用 C 来自己写UDF, ...

  8. php 多条查询结果插入新表,Mysql应用MySQL查询结果复制到新表的方法(更新、插入)...

    <Mysql应用MySQL查询结果复制到新表的方法(更新.插入)>要点: 本文介绍了Mysql应用MySQL查询结果复制到新表的方法(更新.插入),希望对您有用.如果有疑问,可以联系我们. ...

  9. mysql创建用户phpmyadmin_MySQL添加新用户和数据库(命令行模式和phpmyadmin)

    MYSQL添加新用户和数据库(命令行模式和phpmyadmin) 一.命令行模式 首先要声明一下:一般情况下,修改MySQL密码,授权,是需要有mysql里的root权限的. 注:本操作是在WIN命令 ...

最新文章

  1. 某程序员吐槽:组里新来一位美女同事,男同事们冲上去大献殷勤,过几天又一哄而散!...
  2. c语言运行时内存不够,浅析C语言运行时内存管理
  3. Json.net|NH|Log4net|Test等工具下载地址
  4. 微信小程序scroll-wiew 横向滚动问题
  5. php post验证输入,$.post()登录验证功能
  6. 2020年第十八届西电程序设计竞赛网络预选赛之Problem B 祖玛 1
  7. MFC空间几何变换之图像平移、镜像、旋转、缩放
  8. C核心技术手册(四十二)
  9. Java基础学习总结(124)——Java9逆天的十大新特性
  10. Javascript快速排序
  11. 程序结构程序设计(四)
  12. c++builder 代码格式化工具 AStyle
  13. 向量积的坐标运算公式推导_向量外积的直接证明与直观解释,并以此证明正弦公式...
  14. 《把时间当做朋友》读书摘记
  15. 计步器 c语言,ADXL345单片机计步器程序
  16. iphone主屏幕动态壁纸_iPhone不需长按自动触发动态壁纸教程
  17. 联想拯救者y9000x和R9000X有什么区别 选哪个
  18. 罗克韦尔自动化发布2019年企业责任报告,并启动新的企业责任与可持续发展在线内容中心
  19. Java基础语法总复习
  20. html5背景图片铺满整个背景

热门文章

  1. 大数据分析平台的安全如何保障
  2. java学习(一)多态
  3. 安徽省学考计算机操作,安徽省教育考试院全国计算机等级考试网上报名流程与操作步骤...
  4. 服务器安装mysql文档_Linux 服务器安装MySQL数据库
  5. mysql 直方图_MySQL直方图
  6. android线给苹果充电,安卓的充电器可以给iPhone充电吗?这里给你答案
  7. redis的默认配置文件redis.conf详解
  8. spring事务传播行为与事务隔离等级
  9. 唐雄燕点评NFV产业进程:2016年将迎来试点年
  10. 【翻译】RAID, Auto Volume, HBA, Simple Volume模式之间的区别