尚未看完phpJAVA

mysql 为什么有时候order by id效率低

2020-05-11  本文已影响0人  尹楷楷

数据准备,这张tb_box中有100万条数据。有id默认的聚簇索引。然后自己在字段create_time上加了一个索引

CREATE TABLE `test`.`tb_box`  (
  `id` bigint(36) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '创建人',
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
  `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '更新人',
  `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新日期',
  `sys_org_code` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门',
  `status` int(10) NULL DEFAULT 0 COMMENT '状态',
  `number` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '编号',
  `zi_number` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '自编号',
  `house_address` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '仓库地址',
  `sb_number` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '设备id',
  `point_id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '投放点id',
  `point` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '投放点',
  `confirm` int(32) NULL DEFAULT 0 COMMENT '商户/企业用户确认入库,默认为0(未确认)1是已确认',
  `last_point` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '最近一次投放点名',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `a`(`create_time`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1079045 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

先来看看这个where条件中只有create_time ,没有id。然后进行 ORDER BY id desc; 出现了Using filesort。执行时间6.272秒

mysql> EXPLAIN SELECT * FROM tb_box FORCE index(a) WHERE create_time BETWEEN '2020-04-20 10:33:08' AND  '2020-04-23 20:33:08' ORDER BY id desc;
+----+-------------+--------+------------+-------+---------------+-----+---------+------+--------+----------+---------------------------------------+
| id | select_type | table  | partitions | type  | possible_keys | key | key_len | ref  | rows   | filtered | Extra                                 |
+----+-------------+--------+------------+-------+---------------+-----+---------+------+--------+----------+---------------------------------------+
|  1 | SIMPLE      | tb_box | NULL       | range | a             | a   | 6       | NULL | 515010 |   100.00 | Using index condition; Using filesort |
+----+-------------+--------+------------+-------+---------------+-----+---------+------+--------+----------+---------------------------------------+
1 row in set (0.01 sec)

再来看这个,ORDER BY create_time desc。没有出现Using filesort。执行时间3.598 快了将近1半。

mysql> EXPLAIN SELECT * FROM tb_box FORCE index(a) WHERE create_time BETWEEN '2020-04-20 10:33:08' AND  '2020-04-23 20:33:08' ORDER BY create_time  desc;
+----+-------------+--------+------------+-------+---------------+-----+---------+------+--------+----------+-----------------------+
| id | select_type | table  | partitions | type  | possible_keys | key | key_len | ref  | rows   | filtered | Extra                 |
+----+-------------+--------+------------+-------+---------------+-----+---------+------+--------+----------+-----------------------+
|  1 | SIMPLE      | tb_box | NULL       | range | a             | a   | 6       | NULL | 515010 |   100.00 | Using index condition |
+----+-------------+--------+------------+-------+---------------+-----+---------+------+--------+----------+-----------------------+
1 row in set (0.06 sec)

思考:为什么order by id 会出现Using filesort 文件内排序呢?明明id上有索引啊?

因为id没有使用在where条件里!order by id,mysql 的优化器会选择主键索引,但是 where 条件里又没有主键条件,导致全表的id都进行排序。

而 order by create_time ,结合 where 条件里 create_time ,mysq 优化器会选择 create_time 索引,扫描的记录数少,效果更好。

上一篇 下一篇

猜你喜欢

热点阅读