浅谈5.7limit优化

我从远处眺望你,仿佛你消失了一样。--至那些年你以为可以用到,却消失的索引。

 

夜已深,点支烟来记录下今天遇到的问题。

表结构如下所示:

 

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貌似聪明了不少。明天再看结果吧。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(MySQL,MySQL-性能测试与优化)