mysql通过将or改成union来优化sql性能问题一例
来源:互联网 发布:阿里斯顿和史密斯 知乎 编辑:程序博客网 时间:2024/05/18 16:56
某系统测试环境有支SQL执行时间较长,开发人员请求dba协助优化。
原SQL如下:
SELECT g.id,
----省略-----
FROM g,
y,
t,
o
WHERE g.ycon_id = y.id
AND t.ycon_id = g.ycon_id
AND o.bno = t.bno
AND 1 = 1
AND g.t_CODE = 'aa'
AND (g.so_s_n = '123'
OR t.cab_no = '456'
OR t.detail_id IN
(SELECT detail_id
FROM go
WHERE don = '789'))
AND g.status IN ('a7', 'a8')
ORDER BY 1 ASC;
执行时间需要4.08秒。
执行计划如下:
+------+--------------+--------------------+--------+-----------------------------------------------------+---------------------------+---------+------------------------+--------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+--------------------+--------+-----------------------------------------------------+---------------------------+---------+------------------------+--------+------------------------------------+
| 1 | PRIMARY | g | ALL | idx_ycon_id,idx_so_serial_number | NULL | NULL | NULL | 206950 | Using where; Using filesort |
| 1 | PRIMARY | y | eq_ref | id | id | 152 | mg.g.ycon_id | 1 | Using index condition |
| 1 | PRIMARY | t | ref | idx_booking_no,idx_ycon_id,idx_cabinet_no | idx_ycon_id | 123 | mg.y.id | 1 | Using index condition; Using where |
| 1 | PRIMARY | o | ref | unique_booking_no | unique_booking_no | 195 | mg.t.booking_no | 1 | Using index condition |
| 2 | MATERIALIZED | go | ref | idx_booking_req_detail_id,idx_delivery_order_number | idx_delivery_order_number | 99 | const | 1 | Using index condition |
+------+--------------+--------------------+--------+-----------------------------------------------------+---------------------------+---------+------------------------+--------+------------------------------------+
5 rows in set (0.01 sec)
上面显示g表走全表扫描,需要访问206950 行记录,表结构如下:
show create table g\G
........
PRIMARY KEY (`_id`),
UNIQUE KEY `id` (`id`),
KEY `idx_ycon_id` (`ycon_id`),
KEY `idx_so_serial_number` (`so_s_n`)
) ;
对上面sql,通过hint(force index)强制使用索引或强制更改表连接顺序(straight_join),总会有一个表是全表扫描,而且y、t和o表的记录数比g表要大很多。显然,通过直接强制走索引或更改表连接顺序无法达到优化目的。
查看SQL中有两个or连接三个条件,且三个条件的字段都有索引,所以将or改成union,如下:
select a.* from (
SELECT g.id,
----省略-----
FROM g,
y,
t,
o
WHERE g.ycon_id = y.id
AND t.ycon_id = g.ycon_id
AND o.bno = t.bno
AND 1 = 1
AND g.t_CODE = 'aa'
AND g.so_s_n = '123' AND g.status IN ('a7', 'a8')
union
SELECT g.id,
----省略-----
FROM g,
y,
t,
o
WHERE g.ycon_id = y.id
AND t.ycon_id = g.ycon_id
AND o.bno = t.bno
AND 1 = 1
AND g.t_CODE = 'aa'
AND t.cab_no = '456' AND g.status IN ('a7', 'a8')
union
SELECT g.id,
----省略-----
FROM g,
y,
t,
o
WHERE g.ycon_id = y.id
AND t.ycon_id = g.ycon_id
AND o.bno = t.bno
AND 1 = 1
AND g.t_CODE = 'aa'
AND t.detail_id IN
(SELECT detail_id
FROM go
WHERE don = '789') AND g.status IN ('a7', 'a8') )a
order by a.id asc;
执行时间变为0.01秒,执行计划如下:
+------+--------------+--------------------+--------+------------------------------------------------------+---------------------------+---------+----------------------------------------------------+------+------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+--------------------+--------+------------------------------------------------------+---------------------------+---------+----------------------------------------------------+------+------------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 3 | Using filesort |
| 2 | DERIVED | g | ref | idx_ycon_id,idx_so_serial_number | idx_so_serial_number | 195 | const | 1 | Using index condition; Using where |
| 2 | DERIVED | y | eq_ref | id | id | 152 | mg.g.ycon_id | 1 | Using index condition |
| 2 | DERIVED | t | ref | idx_booking_no,idx_ycon_id | idx_ycon_id | 123 | mg.y.id | 1 | Using index condition; Using where |
| 2 | DERIVED | o | ref | unique_booking_no | unique_booking_no | 195 | mg.t.booking_no | 1 | Using index condition |
| 3 | UNION | t | ref | idx_booking_no,idx_ycon_id,idx_cabinet_no | idx_cabinet_no | 99 | const | 1 | Using index condition; Using where |
| 3 | UNION | g | ref | idx_ycon_id | idx_ycon_id | 123 | mg.t.ycon_id | 1 | Using where |
| 3 | UNION | o | ref | unique_booking_no | unique_booking_no | 195 | mg.t.booking_no | 1 | Using index condition |
| 3 | UNION | y | eq_ref | id | id | 152 | mg.t.ycon_id | 1 | Using index condition |
| 4 | UNION | <subquery5> | ALL | distinct_key | NULL | NULL | NULL | 1 | |
| 4 | UNION | t | ref | idx_booking_no,idx_booking_req_detail_id,idx_ycon_id | idx_booking_req_detail_id | 5 | mg.go_shipment_notice.booking_req_detail_id | 1 | Using where |
| 4 | UNION | o | ref | unique_booking_no | unique_booking_no | 195 | mg.t.booking_no | 1 | Using index condition |
| 4 | UNION | g | ref | idx_ycon_id | idx_ycon_id | 123 | mg.t.ycon_id | 1 | Using where |
| 4 | UNION | y | eq_ref | id | id | 152 | mg.t.ycon_id | 1 | Using index condition |
| 5 | MATERIALIZED | go_shipment_notice | ref | idx_booking_req_detail_id,idx_delivery_order_number | idx_delivery_order_number | 99 | const | 1 | Using index condition; Using where |
| NULL | UNION RESULT | <union2,3,4> | ALL | NULL | NULL | NULL | NULL | NULL | |
+------+--------------+--------------------+--------+------------------------------------------------------+---------------------------+---------+----------------------------------------------------+------+------------------------------------+
16 rows in set (0.00 sec)
总结:mysql的sql优化有时需要通过改写sql来优化,通过将or改成union,改变sql执行计划,从而达到提升SQL性能,or改成union提升性能的前提是:or连接的各条件字段要能用到索引。
- mysql通过将or改成union来优化sql性能问题一例
- 【sql 优化】union 、union all、or使用
- SQL优化实例:OR -- UNION
- sql改写or 改成union不等价数据变多
- Sql性能优化之UNION、UNION ALL
- MySQL查询优化UNION操作一例
- SQL索引优化2(MySQL的or/in/union与索引优化)
- 通过内存配置来优化SQL Server的性能
- 通过内存配置来优化SQL Server的性能
- 通过内存配置来优化SQL Server的性能
- 通过内存配置来优化SQL Server的性能
- SQL联合查询优化 用union all来代替union
- SQL联合查询优化 用union all来代替union
- 关于MYSQL索引优化和in or替换为union all的问题
- 【SQL】MySQL性能优化
- MySQL性能优化(一)
- Mysql性能优化一
- Mysql性能优化一
- Tiny210移植u-boot报/usr/local/include/asm/io.h文件中未知的类型名错误
- 使用MyBatis自动创建代码
- redis入门笔记
- 爬虫实例:唐诗三百首
- struct file struct inode
- mysql通过将or改成union来优化sql性能问题一例
- 我上了985,211,才发现自己一无所有 | 或者,也不能这么说
- 爬虫实例:从百度图片下载壁纸
- php文件上传格式列表
- 免备案速度快最新优惠码,vps评测vultr对比linode
- 利用Java实现Base64加解密
- jump horse
- 渗透利器Weevely之奇淫技巧篇
- Tiny210(S5PV210) U-BOOT(一)----启动过程