在一下查询的时候,虽然都是使用RAND()<(20/100)
进行随机筛选数据,但是前者获取的比例并不在20%左右,而是在5%左右。
唯一不同的地方在与子查询里面的条件a.pos_sn = b.pos_sn
和 a.merchant_code = b.merchant_code
,并且其他条件都一样。
【这两个条件不影响子查询的结果,子查询的结果是一模一样的】
问题代码,随机数来的概率小很多,改成RAND()<(0.7)又突然概率超过70% ε=(´ο`*)))唉
explain
select p_i.*
from table_order o_i
left join (
select a.order_id as order_id,IFNULL(sum(b.trade_amount),0) as sumamount
from table_info a
left join table_deal b on a.merchant_code = b.merchant_code --出问题的条件
GROUP BY a.order_id
) t_a on t_a.order_id = o_i.id
left join table_info p_i on p_i.order_id = o_i.id
where t_a.sumamount = 0 and RAND()<(20/100) --就是这里 随机一下
and p_i.id is not null
数据量为450 概率结果为 10-50之间跳动
分析结果:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY ALL 2 50 Using where
1 PRIMARY o_i eq_ref PRIMARY,idx_pou PRIMARY 8 t_a.order_id 1 5 Using where
1 PRIMARY p_i ref PRIMARY,idx_pos_opu_id idx_pos_opu_id 8 t_a.order_id 222042 90 Using index condition
2 DERIVED a range idx_pos_opu_id idx_pos_opu_id 8 2 10 Using index condition; Using where; Using temporary; Using filesort
2 DERIVED b range pos_sn,idx_trade_time idx_trade_time 6 1 100 Using where; Using join buffer (Block Nested Loop)
1 PRIMARY ALL 2 50 Using where
这个代码是没问题的,可以使用
explain
select p_i.*
from table_order o_i
left join (
select a.order_id as order_id,IFNULL(sum(b.trade_amount),0) as sumamount
from table_info a
left join table_deal b on a.pos_sn = b.pos_sn --出问题的条件
GROUP BY a.order_id
) t_a on t_a.order_id = o_i.id
left join table_info p_i on p_i.order_id = o_i.id
where t_a.sumamount = 0 and RAND()<(20/100) --就是这里 随机一下
and p_i.id is not null
** 数据量为450 概率结果为 80-120之间跳动**
分析结果:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY o_i ALL PRIMARY 25 4 Using where
1 PRIMARY p_i ref PRIMARY,idx_pos_opu_id idx_pos_opu_id 8 chuangshoubao.o_i.id 12865 90 Using index condition
1 PRIMARY ref 23 chuangshoubao.o_i.id,const 10 100 Using where; Using index
2 DERIVED a range idx_pos_opu_id idx_pos_opu_id 8 662 10 Using index condition; Using where
2 DERIVED b ref idx_mer_code,idx_trade_time idx_mer_code 96 chuangshoubao.a.merchant_code 10 100 Using where
1 PRIMARY ref
根据参考资料:https://www.cnblogs.com/lYng/p/9441467.html
这里的derived是叫做派生表的东东:解释为子查询–>在From后where前的子查询 。
MySQL 5.7开始优化器引入derived_merge,可以理解为Oracle的子查询展开,有优化器参数optimizer_switch='derived_merge=ON’来控制,默认为打开。
但是仍然有很多限制,当派生子查询存在以下操作时该特性无法生效:UNION 、GROUP BY、DISTINCT、LIMIT/OFFSET以及聚合操作
这里对比之后,猜测是索引之类的导致有问题的SQL子查询,使用了全表查询。
最后在核对了索引之后,结果依旧。【索引没有问题】
最后,发现是merchant_code这个字段被设置为is not null 导致的【这个是pos_sn字段唯一的区别了】
去掉不为空的限制之后,就突然妥妥的没问题了(ノ`Д)ノ
完全不知道这中间发生了什么?.?
路过的大佬,有没有了解的,留个资料链接呀
2019-03-13 小杭