前些天,有个同事跟我说:“我写了个SQL,SQL很简单,然则萌芽速度很慢,并且针对萌芽前提创建了索引,然而索引却不起感化,你帮我看看竽暌剐没有办法优化?”。
我对他供给的case进行了优化,并将优化过程整顿了下来。
我们先来看看竽暌古化前的表构造、数据量、SQL、履行筹划、履行时光等。
1. 表构造:
- CREATE TABLE `t_order` (
- `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
- `order_code` char(12) NOT NULL,
- `order_amount` decimal(12,2) NOT NULL,
- PRIMARY KEY (`id`),
- UNIQUE KEY `uni_order_code` (`order_code`) USING BTREE
- ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
隐蔽了部分不相干字段后,可以看到表足够简单, 并且在order_code上创建了独一性索引uni_order_code。
2. 数据量:316977
这个数据量照样比较小的,不过如不雅SQL足够差,一样会萌芽很慢。
3. SQL:
哇,SQL足够简单,不过有时刻越简单也越难优化。
- select order_code, order_amount from t_order order by order_code limit 1000;
4. 履行筹划:
id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t_order ALL NULL NULL NULL NULL 316350 Using filesort全表扫描、文件排序,注定萌芽慢!
那为什么MySQL没有应用索引(uni_order_code)扫描完成萌芽呢?因为MySQL认为这个场景应用索引扫描并非最优的结不雅。我们先来看下履行时光,然后再来分析为什么没有应用索引扫描。
我们来看看应用覆盖索引优化后的索引、履行筹划、履行时光。
5. 履行时光:260ms

切实其实,履行时光太长了,如不雅表数据量持续增长下去,机能会越来越差。
1. 全表扫描、文件排序:
2. 应用索引扫描、应用索引次序:
uni_order_code是二级索引,索引上保存了(order_code,id),每扫描一条索引须要根据索引上的id定位(随机IO)到数据行上攫取order_amount,须要1000次随机IO才能完成萌芽,而机械硬盘随机IO的效力是极低的(机械硬盘每秒寻址几百次)。
根据我们本身的分析选择全表扫描相对更优。如不雅把limit 1000改成limit 10,则履行筹划会完全不一样。
既然我们已经知道是因为随机IO导致无法应用索引,那么竽暌剐没有办法清除随机IO呢?
有,覆盖索引。
1. 创建索引:
- ALTER TABLE `t_order`
- ADD INDEX `idx_ordercode_orderamount` USING BTREE (`order_code` ASC, `order_amount` ASC);
创建了复合索引idx_ordercode_orderamount(order_code,order_amount),将select的列order_amount也放到索引中。
推荐阅读
结缘:我小我很爱好研究马云的研究,一是认为他把工作做到了弗成思议的高度,二是他很爱对将来思虑场且愿意把结不雅分享。可以或许接触他的思惟,是一件异常荣幸的工作。我踏入数据行业也>>>详细阅读
本文标题:MySQL SQL优化之覆盖索引
地址:http://www.17bianji.com/lsqh/37146.html
1/2 1

网友点评
精彩导读
科技快报
品牌展示