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

本文涉及的产品
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDSClaw,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. 

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
10月前
|
SQL 缓存 关系型数据库
MySQL 慢查询是怎样优化的
本文深入解析了MySQL查询速度变慢的原因及优化策略,涵盖查询缓存、执行流程、SQL优化、执行计划分析(如EXPLAIN)、查询状态查看等内容,帮助开发者快速定位并解决慢查询问题。
410 0
|
7月前
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。
|
SQL 关系型数据库 MySQL
MySQL进阶突击系列(07) 她气鼓鼓递来一条SQL | 怎么看执行计划、SQL怎么优化?
在日常研发工作当中,系统性能优化,从大的方面来看主要涉及基础平台优化、业务系统性能优化、数据库优化。面对数据库优化,除了DBA在集群性能、服务器调优需要投入精力,我们研发需要负责业务SQL执行优化。当业务数据量达到一定规模后,SQL执行效率可能就会出现瓶颈,影响系统业务响应。掌握如何判断SQL执行慢、以及如何分析SQL执行计划、优化SQL的技能,在工作中解决SQL性能问题显得非常关键。
|
8月前
|
缓存 关系型数据库 MySQL
降低MySQL高CPU使用率的优化策略。
通过上述方法不断地迭代改进,在实际操作中需要根据具体场景做出相对合理判断。每一步改进都需谨慎评估其变动可能导致其他方面问题,在做任何变动前建议先在测试环境验证其效果后再部署到生产环境中去。
334 6
|
9月前
|
存储 SQL 关系型数据库
MySQL 核心知识与索引优化全解析
本文系统梳理了 MySQL 的核心知识与索引优化策略。在基础概念部分,阐述了 char 与 varchar 在存储方式和性能上的差异,以及事务的 ACID 特性、并发事务问题及对应的隔离级别(MySQL 默认 REPEATABLE READ)。 索引基础部分,详解了 InnoDB 默认的 B+tree 索引结构(多路平衡树、叶子节点存数据、双向链表支持区间查询),区分了聚簇索引(数据与索引共存,唯一)和二级索引(数据与索引分离,多个),解释了回表查询的概念及优化方法,并分析了 B+tree 作为索引结构的优势(树高低、效率稳、支持区间查询)。 索引优化部分,列出了索引创建的六大原则
228 2
|
11月前
|
存储 SQL 关系型数据库
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
京东面试:mysql深度分页 严重影响性能?根本原因是什么?如何优化?
|
9月前
|
存储 SQL 关系型数据库
MySQL 动态分区管理:自动化与优化实践
本文介绍了如何利用 MySQL 的存储过程与事件调度器实现动态分区管理,自动化应对数据增长,提升查询性能与数据管理效率,并详细解析了分区创建、冲突避免及实际应用中的关键注意事项。
395 0
|
存储 关系型数据库 MySQL
MySQL细节优化:关闭大小写敏感功能的方法。
通过这种方法,你就可以成功关闭 MySQL 的大小写敏感功能,让你的数据库操作更加便捷。
1037 19
|
关系型数据库 MySQL 大数据
大数据新视界--大数据大厂之MySQL 数据库课程设计:MySQL 数据库 SQL 语句调优的进阶策略与实际案例(2-2)
本文延续前篇,深入探讨 MySQL 数据库 SQL 语句调优进阶策略。包括优化索引使用,介绍多种索引类型及避免索引失效等;调整数据库参数,如缓冲池、连接数和日志参数;还有分区表、垂直拆分等其他优化方法。通过实际案例分析展示调优效果。回顾与数据库课程设计相关文章,强调全面认识 MySQL 数据库重要性。为读者提供综合调优指导,确保数据库高效运行。
|
存储 SQL 关系型数据库
服务器数据恢复—云服务器上mysql数据库数据恢复案例
某ECS网站服务器,linux操作系统+mysql数据库。mysql数据库采用innodb作为默认存储引擎。 在执行数据库版本更新测试时,操作人员误误将在本来应该在测试库执行的sql脚本在生产库上执行,导致生产库上部分表被truncate,还有部分表中少量数据被delete。
341 25

推荐镜像

更多