一个MySQL优化案例的初步思路(r8笔记第87天)
今天想起这件同事处理的一个性能优化案例,当时虽然解决了,但是还是留下了几个未解的问题,和大家一起讨论一下。
首先,这个问题是根据反馈sql响应很慢,已经开始影响前端应用的登录了。稍后DBA介入,发现是由于CPU使用率过高导致,为了能够延缓问题和进一步分 析,因为数据库中的数据量不大,直接就迁移到了另外一台配置不错的服务器上,但是迁移之后,CPU配置好了很多,问题依旧,同时也在进行问题的诊断和分 析。
得到的慢日志如下,发现大多数的响应时间都耗费在了两个SQL上,其实出自同一个存储过程。
1、慢日志
# Profile
# Rank Query ID Response time Calls R/Call V/M Item
# ==== ================== =============== ===== ======= ===== ============
# 1 0x26EEFEA86049462C 7667.3733 44.3% 189 40.5681 6.88 CALL p_register_check_1021e
# 2 0x6D5C3CEFC40B5E28 7518.4182 43.5% 189 39.7800 6.10 UPDATE push_list_s
两个查询的统计信息如下:
# Query 1: 0.30 QPS, 12.15x concurrency, ID 0x26EEFEA86049462C at byte 976472
# This item is included in the report because it matches --limit.
# Scores: V/M = 6.88
# Time range: 2015-11-02 21:41:53 to 21:52:24
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 3 189
# Exec time 44 7667s 1s 90s 41s 57s 17s 45s
# Query 2: 0.30 QPS, 11.92x concurrency, ID 0x6D5C3CEFC40B5E28 at byte 1397182
# This item is included in the report because it matches --limit.
# Scores: V/M = 6.10
# Time range: 2015-11-02 21:41:53 to 21:52:24
# Attribute pct total min max avg 95% stddev median
# ============ === ======= ======= ======= ======= ======= ======= =======
# Count 3 189
# Exec time 43 7518s 1s 77s 40s 57s 16s 45s
# Lock time 30 65s 13us 19s 343ms 21us 2s 18us
相关的SQL语句如下
# Converted for EXPLAIN
# EXPLAIN /*!50100 PARTITIONS*/
select APNS_PUSH_ID = `ID` from push_list_s where APNS_PUSH_ID = NAME_CONST('i_apnsPushId',_utf8'eb43f3f09940de7228a780f69d05eab0a9df98083c701e23d11c7494a980b351' COLLATE 'utf8_general_ci')G
涉及的表只有一个,表结构如下:
Create Table: CREATE TABLE `push_list_s` (
`ID` int(10) NOT NULL AUTO_INCREMENT,
`SN_LIST_ID` int(10) NOT NULL DEFAULT '0',
。。。
`APNS_PUSH_ID` varchar(64) CHARACTER SET latin1 NOT NULL DEFAULT '""',
。。。
PRIMARY KEY (`ID`),
UNIQUE KEY `INDEX_SN_LIST_ID` (`SN_LIST_ID`),
UNIQUE KEY `APNS_PUSH_ID` (`APNS_PUSH_ID`),
KEY `INDEX_CABLE_PUSH_ID` (`CABLE_PUSH_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2181938 DEFAULT CHARSET=utf8
整个调用过程的要点如下,里面有一个update操作,字段APNS_PUSH_ID为varchar
IF (LENGTH(i_apnsPushId)=64) THEN
UPDATE push_list_s SET APNS_PUSH_ID = `ID` WHERE APNS_PUSH_ID = i_apnsPushId;
END IF;
运行的语句类似下面的形式:
UPDATE push_list_s SET APNS_PUSH_ID = `ID` WHERE APNS_PUSH_ID = 'eb43f3f09940de7228a780f69d05eab0a9df98083c701e23d11c7494a980b351';
初步的分析怀疑是由于索引为字符过长导致,所以根据表的结构信息,其实就是转换到了数字类型的字段上。
修改后的部分如下:
IF (LENGTH(i_apnsPushId)=64) THEN
select ID into v_id from push_list_s WHERE APNS_PUSH_ID = i_apnsPushId;
IF (v_id > 0) THEN
UPDATE push_list_s SET APNS_PUSH_ID = v_id WHERE ID = v_id;
END IF;
END IF;
这是优化前后的对比效果图:
目前对于这个问题的疑问如下:
1.对于字符型字段作为索引,目前来看没有很直接的原因使得字符型索引和数字型索引存在巨大的差别。从后来我单独得到的执行计划和后来复现情况来看,没有发现存在很巨大的差别。
2.对于慢日志中得到的语句,看到内部已经做了转换。
UPDATE push_list_s SET APNS_PUSH_ID = `ID` WHERE APNS_PUSH_ID = NAME_CONST('i_apnsPushId',_utf8'eb43f3f09940de7228a780f69d05eab0a9df98083c701e23d11c7494a980b351' COLLATE 'utf8_general_ci')G
而对于这种转换,可能关注点都在NAME_CONST这个部分,在查看了一些资料之后,发现在其他版本和环境中,主要是和字符集转换有关,但是我查看了当前环境的这些配置信息,没有发现有相匹配的信息
3.关于这个问题,在5.1版本中发现了相应的bug描述,但是目前的环境是在5.6,所以应该也不是相关。
关于这个问题的进一步分析,我希望得到一些确切的信息,能够复现,能够找到一些相关的bug或者相关的解决方案(除了使用数字型字符临时替换的方案)
- Python 项目实践三(Web应用程序)第二篇
- 第一个IronPython程序(之一)
- mono-3.4.0 源码安装时出现的问题 [do-install] Error 2 [install-pcl-targets] Error 1 解决方法
- 安装 IronPython
- Python 项目实践三(Web应用程序)第一篇
- Centos 7.0 安装Mono 3.4 和 Jexus 5.6
- 第一个IronPython程序(之二)
- Python 项目实践二(下载数据)第四篇
- Python 项目实践二(下载数据)第三篇
- 体验扁平化的WordPress 后台管理界面
- Python 项目实践二(生成数据)第二篇
- 重新审视SqlDataReader的使用
- Python 项目实践二(生成数据)第一篇
- 删除 WordPress 导航菜单的多余 CSS 选择器
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解
- Borg:Google集群管理大杀器
- 一文了解Zookeeper
- 【投稿】刀哥:Rust学习笔记 4
- Spring Boot 运行源码剖析
- Spring Boot 特性之 Lazy
- Spring Boot 特性之 Banner
- Spring Boot 特性之 Fluent Builder API
- 一文搞懂 Flink Timer
- DATE类型的“小陷阱”
- 简单聊下 Java Agent
- Byte Buddy 基础知识
- 两种在SAP Cloud Application Studio里通过编程对C4C UI字段赋值的方法
- 如何使用 BTrace v.2.0.1
- 三分钟写一个 Java 多线程
- 使用纯粹的ABAP位操作实现两个整数相加