记一次sql优化,in+子查询
2017-10-17 17:44
381 查看
拿到一个sql,同事告诉我这个sql索引加了,为什么还是这么慢。
sale_order_goods,sale_order 两张表都有几十万的数据。其中in结果集有30万。
sql如下:
这是一个in + 子查询的语句。
顺便提一句,innodb对in + 子查询的处理非常差,比如:
这时,子查询关联外部表a,所以innodb认为无法执行这个子查询,于是需要全表遍历一遍a,再根据a返回的oid逐个执行一次子查询。
上面这个sql不需要执行子查询,改写如下:
直接放弃 in + 子查询的方式。sql在1秒内执行完毕。
sale_order_goods,sale_order 两张表都有几十万的数据。其中in结果集有30万。
sql如下:
SELECT ifnull(sum(buy_number), 0) AS buy_number_sum FROM sale_order_goods WHERE sale_order_id IN ( SELECT so.id FROM sale_order_goods sog, sale_order so WHERE 1 = 1 AND sog.tenant_org_id =1 AND so.tenant_org_id =1 AND sog.sale_order_id = so.id AND so.order_status =1 AND DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(sog.created_at) );
这是一个in + 子查询的语句。
顺便提一句,innodb对in + 子查询的处理非常差,比如:
select * from a where a.oid in (select id from b where b.name='xxx'),如果
select id from b where b.name='xxx'返回的结果是1,2,3。那么sql是不是就变成了
select * from a where a.oid in (1,2,3). NO!!,事实上不是这样。innodb会把外层表压入到子查询中,sql会变成
select * from a exists (select * from b where name='xxx' and b.id = a.oid)
这时,子查询关联外部表a,所以innodb认为无法执行这个子查询,于是需要全表遍历一遍a,再根据a返回的oid逐个执行一次子查询。
上面这个sql不需要执行子查询,改写如下:
SELECT ifnull(sum(buy_number), 0) AS buy_number_sum FROM sale_order_goods sog, sale_order so WHERE 1 = 1 AND sog.tenant_org_id =1 AND so.tenant_org_id =1 AND sog.sale_order_id = so.id AND so.order_status =1 AND DATE_SUB(CURDATE(), INTERVAL 30 DAY) <= date(sog.created_at)
直接放弃 in + 子查询的方式。sql在1秒内执行完毕。
相关文章推荐
- 一次查询一条数据花费6分钟的SQL优化到0.05s的经历
- 一次SQL查询语句的优化
- 记一次苦逼的Sql查询优化
- 记一次苦逼的SQL查询优化
- SQL优化一则:CBO查询SQL一次比一次慢
- 记一次T-SQL查询优化 索引的重要性
- 记一次苦逼的SQL查询优化
- 记一次T-SQL查询优化 索引的重要性
- 一次层次查询相关的sql的调整优化
- 记一次苦逼的Sql查询优化
- 一次sql查询优化 并行度
- 记一次苦逼的Sql查询优化
- 记一次苦逼的SQL查询优化
- SQL存储过程事务和优化方法(包括查询方式语句结合)
- oracle 查询优化及sql改写
- T-SQL 查询优化之聚合
- 一次ORA-4030问题诊断及解决【解决思路不错,说明了对象的统计信息与优化器的优化操作(即选择执行一个SQL语句在该优化参数环境下最佳的执行计划)间的关系】
- 【职坐标】Mysql中查询SQL优化的常用方法(一)
- 表量子查询优化SQL
- 一次非常有意思的 SQL 优化经历