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秒内执行完毕。