【案例】MySQL count操作优化案例一则

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介:
一 背景

 某业务的数据库定期报 thread_runing 飙高,通定位发现一个慢查询sql导致会话堆积。执行sql 耗时如下


root@db 05:32:05>select count(item_id) from xxxtable where selid = 345705650 and end_time > now();
 
+----------------+

| count(item_id) |

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

| 2247052 |

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

1 row in set (4.65 sec) 

二 分析   
慢查询表结构如下 


root@db >show create table xxxtable \G
 
*************************** 1. row ***************************

       Table: uac_shop_item_promotion_0091

Create Table: CREATE TABLE `uac_shop_item_promotion_0091` (

  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',

  `gmt_modified` datetime NOT NULL COMMENT '修改时间',

  `selid` bigint(20) NOT NULL COMMENT '分表字段',

  `end_time` datetime NOT NULL COMMENT '活动结束时间',

  `item_id` bigint(20) NOT NULL COMMENT '商品id',

  PRIMARY KEY (`id`),

  UNIQUE KEY `idx_uq_item` (`item_id`),

  KEY `idx_deller_id_end_time` (`selid`,`end_time`),

  KEY `idx_deller_id_start_time` (`selid`,`start_time`),

  KEY `idx_seller_item_start` (`selid`,`start_time`,`item_id`)

) ENGINE=InnoDB AUTO_INCREMENT=42132149 DEFAULT CHARSET=gbk COMMENT='索引表'

1 row in set (0.00 sec) 

很明显出现问题的sql由于使用了count(item_id) ,而item_id字段并没有和 selid 和end_time 构成有效索引  故该sql 没有合理的使用索引 。查看其直系计划


root@db >explain select count(item_id) from xxxtable 
 
        >where selid = 345705650 and end_time > now() \G

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

           id: 1

  select_type: SIMPLE

        table: xxxtable

         type: ref

possible_keys: idx_deller_id_end_time,idx_deller_id_start_time,idx_seller_item_start

          key: idx_deller_id_end_time

      key_len: 8 

          ref: const

         rows: 1726757

        Extra: Using where

1 row in set (0.00 sec) 

从key_len=8 和Extra: Using where 可以看出MySQL没有完全利用到idx_deller_id_end_time组合索引而是利用到了 selid字段作为过滤条件回表查询。
count(item_id)的意思是符合where条件的结果集中item_id非空集合的总和。
三 如何优化
根据该sql的业务需求是需要获取到某商家参加活动且活动截止时间大于当前时间的商品总数,可以使用如下sql满足要求:


select count(*) from xxxtable where selid = 345705650 and end_time > now() 

执行时间仅为原来的1/4,新的sql发布之后thread_running报警消失,业务校验时间明显缩短。


root@db >select count(*) from xxxtable where selid = 345705650 and end_time > now();
 
+----------+

| count(*) |

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

| 2247052 |

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

1 row in set (0.82 sec)

root@db >select count(1) from xxxtable where selid = 345705650 and end_time > now();

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

| count(1) |

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

| 2247052 |

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

1 row in set (0.79 sec) 

优化后的sql的explain 方式如下:


root@db >explain select count(*) from xxxtable where selid = 345705650 and end_time > now() \G
 
*************************** 1. row ***************************

           id: 1

  select_type: SIMPLE

        table: xxxtable

         type: range

possible_keys: idx_deller_id_end_time,idx_deller_id_start_time,idx_seller_item_start

          key: idx_deller_id_end_time

      key_len: 16

          ref: NULL

         rows: 1726768

        Extra: Using where; Using index

1 row in set (0.00 sec) 

四 小结
 a 这个问题是在没有修改索引的基础中做出的优化,老的sql没有有效的利用当前的索引导致耗时操作
 b 对于不同count类型的sql 总结如下
   count(*)/count(1) 返回结果集的总和包括null和重复的值。
   count(column) 返回结果集中非空 column 的总和,执行查询的过程中会校验字段是否非空。
 c 在业务设计的时候 满足业务逻辑的前提下推荐使用count(*).
 d 从官方文档中摘录 Using where 和 Using index 的区别 


Using index
 
 The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.

 If the Extra column also says Using where, it means the index is being used to perform lookups of key values. Without Using where, the optimizer may be reading the index to avoid reading data rows but not using it for lookups. For example, if the index is a covering index for the query, the optimizer may scan it without using it for lookups. For InnoDB tables that have a user-defined clustered index, that index can be used even when Using index is absent from the Extra column. This is the case if type is index and key is PRIMARY.

 Using where

 A WHERE clause is used to restrict which rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the Extra value is not Using where and the table join type is ALL or index. Even if you are using an index for all parts of a WHERE clause, you may see Using where if the column can be NULL. 

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
16天前
|
SQL 关系型数据库 MySQL
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
117 9
|
2月前
|
SQL 关系型数据库 MySQL
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
MySQL慢查询优化、索引优化,是必知必备,大厂面试高频,本文深入详解,建议收藏。关注【mikechen的互联网架构】,10年+BAT架构经验分享。
大厂面试官:聊下 MySQL 慢查询优化、索引优化?
|
12天前
|
存储 缓存 关系型数据库
MySQL的count()方法慢
MySQL的 `COUNT()`方法在处理大数据量时可能会变慢,主要原因包括数据量大、缺乏合适的索引、InnoDB引擎的设计以及复杂的查询条件。通过创建合适的索引、使用覆盖索引、缓存机制、分区表和预计算等优化方案,可以显著提高 `COUNT()`方法的执行效率,确保数据库查询性能的提升。
129 12
|
21天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
60 18
|
11天前
|
存储 关系型数据库 MySQL
10个案例告诉你mysql不使用子查询的原因
大家好,我是V哥。上周与朋友讨论数据库子查询问题,深受启发。为此,我整理了10个案例,详细说明如何通过优化子查询提升MySQL性能。主要问题包括性能瓶颈、索引失效、查询优化器复杂度及数据传输开销等。解决方案涵盖使用EXISTS、JOIN、IN操作符、窗口函数、临时表及索引优化等。希望通过这些案例,帮助大家在实际开发中选择更高效的查询方式,提升系统性能。关注V哥,一起探讨技术,欢迎点赞支持!
|
20天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化以及慢查询优化
通过本文的介绍,希望您能够深入理解MySQL索引优化和慢查询优化的方法,并在实际应用中灵活运用这些技术,提升数据库的整体性能。
22 7
|
19天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
50 5
|
25天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。
|
2月前
|
SQL 关系型数据库 MySQL
MySQL慢查询优化、索引优化、以及表等优化详解
本文详细介绍了MySQL优化方案,包括索引优化、SQL慢查询优化和数据库表优化,帮助提升数据库性能。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
MySQL慢查询优化、索引优化、以及表等优化详解
|
21天前
|
缓存 NoSQL 关系型数据库
MySQL战记:Count( *)实现之谜与计数策略的选择
本文深入探讨了MySQL中`count(*)`的不同实现方式,特别是MyISAM和InnoDB引擎的区别,以及各种计数方法的性能比较。同时,文章分析了使用缓存系统(如Redis)与数据库保存计数的优劣,并强调了在高并发场景下保持数据一致性的挑战。
MySQL战记:Count( *)实现之谜与计数策略的选择