浅谈5.7limit优化
2015-12-24 01:10
253 查看
我从远处眺望你,仿佛你消失了一样。--至那些年你以为可以用到,却消失的索引。
夜已深,点支烟来记录下今天遇到的问题。
表结构如下所示:
pay_flow | CREATE TABLE `pay_flow` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uuid` varchar(36) NOT NULL ,
`flow_type` tinyint(4) NOT NULL ,
`amount` varchar(20) NOT NULL ,
`create_time` timestamp NOT NULL ,
`operation_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`pay_id` varchar(36) NOT NULL COMMENT '支付系统的唯一ID',
`flow_status` tinyint(4) NOT NULL ,
`user_uuid` varchar(36) DEFAULT NULL COMMENT '用户ID',
`tf_uuid` varchar(20) NOT NULL DEFAULT ' ' COMMENT '交易明细ID',
`ti_uuid` varchar(20) NOT NULL DEFAULT ' ' COMMENT '还款明细ID',
`pay_status` tinyint(4) DEFAULT NULL COMMENT '1:成功,2:失败,3:需要支付,4:进行中',
`original_tf_uuid` varchar(35) NOT NULL DEFAULT '0' COMMENT '原始的链条ID',
PRIMARY KEY (`id`),
UNIQUE KEY `index_user_payid_status` (`user_uuid`,`pay_id`,`flow_status`),
KEY `pay_id` (`pay_id`),
KEY `create_time` (`create_time`),
KEY `index_original_tf_uuid` (`original_tf_uuid`),
KEY `idx_uuid` (`uuid`)
) ENGINE=InnoDB AUTO_INCREMENT=154098216
sql如下:
SELECT * FROM `pay_flow` WHERE user_uuid='511933977553843466' ORDER BY `create_time` DESC LIMIT 50;
5.6.23版本的查询计划如下:
mysql> explain SELECT * FROM `pay_flow` WHERE user_uuid='511933977553843466' ORDER BY `create_time` DESC LIMIT 50;
+----+-------------+----------+-------+-------------------------+-------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+-------------------------+-------------+---------+------+-------+-------------+
| 1 | SIMPLE | pay_flow | index | index_user_payid_status | create_time | 4 | NULL | 54309 | Using where |
+----+-------------+----------+-------+-------------------------+-------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
抛开查询计划,闭着眼都知道,就当前的表结构而言,走user_uuid列的索引,会使得查询更快,mysql只需沿着索引列向下寻找大概不到30次就能完全找到所需要的uuid结果,然后会回表取出所有数据,根据create_time列排序,取前50,便可以得到最终想要的结果。然后根据5.6的查询计划,可能要花费2的N次方的时间才可以了。
然而,当我们舍弃limit后,5.6又会呈现出另外一种查询计划出来。
mysql> explain SELECT * FROM `pay_flow` WHERE user_uuid='511933977553843466' ORDER BY `create_time` DESC;
+----+-------------+----------+------+-------------------------+-------------------------+---------+-------+-------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+-------------------------+-------------------------+---------+-------+-------+----------------------------------------------------+
| 1 | SIMPLE | pay_flow | ref | index_user_payid_status | index_user_payid_status | 111 | const | 57072 | Using index condition; Using where; Using filesort |
+----+-------------+----------+------+-------------------------+-------------------------+---------+-------+-------+----------------------------------------------------+
1 row in set (0.00 sec)
终于正常的如我们想象的那样,不明白的是,为什么当遇到limit之后,mysql就糊涂了呢。我读书少,别骗我。
正常的查询,来看5.7的表现:
5.7貌似聪明了不少。明天再看结果吧。
夜已深,点支烟来记录下今天遇到的问题。
表结构如下所示:
pay_flow | CREATE TABLE `pay_flow` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`uuid` varchar(36) NOT NULL ,
`flow_type` tinyint(4) NOT NULL ,
`amount` varchar(20) NOT NULL ,
`create_time` timestamp NOT NULL ,
`operation_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`pay_id` varchar(36) NOT NULL COMMENT '支付系统的唯一ID',
`flow_status` tinyint(4) NOT NULL ,
`user_uuid` varchar(36) DEFAULT NULL COMMENT '用户ID',
`tf_uuid` varchar(20) NOT NULL DEFAULT ' ' COMMENT '交易明细ID',
`ti_uuid` varchar(20) NOT NULL DEFAULT ' ' COMMENT '还款明细ID',
`pay_status` tinyint(4) DEFAULT NULL COMMENT '1:成功,2:失败,3:需要支付,4:进行中',
`original_tf_uuid` varchar(35) NOT NULL DEFAULT '0' COMMENT '原始的链条ID',
PRIMARY KEY (`id`),
UNIQUE KEY `index_user_payid_status` (`user_uuid`,`pay_id`,`flow_status`),
KEY `pay_id` (`pay_id`),
KEY `create_time` (`create_time`),
KEY `index_original_tf_uuid` (`original_tf_uuid`),
KEY `idx_uuid` (`uuid`)
) ENGINE=InnoDB AUTO_INCREMENT=154098216
sql如下:
SELECT * FROM `pay_flow` WHERE user_uuid='511933977553843466' ORDER BY `create_time` DESC LIMIT 50;
5.6.23版本的查询计划如下:
mysql> explain SELECT * FROM `pay_flow` WHERE user_uuid='511933977553843466' ORDER BY `create_time` DESC LIMIT 50;
+----+-------------+----------+-------+-------------------------+-------------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+-------------------------+-------------+---------+------+-------+-------------+
| 1 | SIMPLE | pay_flow | index | index_user_payid_status | create_time | 4 | NULL | 54309 | Using where |
+----+-------------+----------+-------+-------------------------+-------------+---------+------+-------+-------------+
1 row in set (0.00 sec)
抛开查询计划,闭着眼都知道,就当前的表结构而言,走user_uuid列的索引,会使得查询更快,mysql只需沿着索引列向下寻找大概不到30次就能完全找到所需要的uuid结果,然后会回表取出所有数据,根据create_time列排序,取前50,便可以得到最终想要的结果。然后根据5.6的查询计划,可能要花费2的N次方的时间才可以了。
然而,当我们舍弃limit后,5.6又会呈现出另外一种查询计划出来。
mysql> explain SELECT * FROM `pay_flow` WHERE user_uuid='511933977553843466' ORDER BY `create_time` DESC;
+----+-------------+----------+------+-------------------------+-------------------------+---------+-------+-------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+-------------------------+-------------------------+---------+-------+-------+----------------------------------------------------+
| 1 | SIMPLE | pay_flow | ref | index_user_payid_status | index_user_payid_status | 111 | const | 57072 | Using index condition; Using where; Using filesort |
+----+-------------+----------+------+-------------------------+-------------------------+---------+-------+-------+----------------------------------------------------+
1 row in set (0.00 sec)
终于正常的如我们想象的那样,不明白的是,为什么当遇到limit之后,mysql就糊涂了呢。我读书少,别骗我。
正常的查询,来看5.7的表现:
5.7貌似聪明了不少。明天再看结果吧。
相关文章推荐
- [ISUX译]iOS 9人机界面指南(二):设计策略
- 高德地图搜索提示获取信息回传activity刷新ui(二)
- 运算符重载的例子
- Eclipse导入Maven工程报异常
- LNMP nginx配置和 php-fpm通道详解
- Maven settings 开源中国 镜像并下载本地仓库
- [ISUX译]iOS 9人机界面指南(一):UI设计基础
- HTTP协议
- 日期的格式,你用得对吗?
- ZOJ 1049 I Think I Need a Houseboat
- Result Maps collection already contains value for xxxMapper.BaseResultMap错误解决办法
- win7配置maven环境变量
- Block的简介和简单原理
- 网络编程:Reactor与Proactor的概念
- 不好好说话版原理(二)ORACLE数据库的连接
- Block在ARC和非ARC中的使用
- 删除linux系统服务
- android的线性布局
- echarts中显示效果option中必有的属性
- ASP.NET中最保险最环保的返回404的方法