mysql在做每次子查询时是否会缓存上次子查询的结果?

        以前一直以为数据库在做子查询时会重新做全部的查询,后来发现postgresql在做子查询时如果

来自父查询的参数未发生改变,那么其是可以直接计算结果而不用再次执行子查询的,那么mysql是怎么

处理的呢,再次翻出mysql(5.6.10)的源码简单调试了下发现以下结论:

1. 在执行子查询无关的exists not exists时如:select  * from a where exists(select * from b);那么在执

行Join::optimize函数时将自动执行子查询select  * from b得到结果作为a扫描的条件,虽然呈现的执行

计划如下:


对于类似于select * from a where a > all(select * from b);这里其查询计划如下:


其中的select * from b的结果将会被缓存起来,下次执行子查询时可以直接取出子查询的结果.

这是因为如下代码的作用:

  subselect_single_select_engine::exec
  if (select_lex->uncacheable &&
      select_lex->uncacheable != UNCACHEABLE_EXPLAIN
      && executed)
  {
    join->reset();
    item->reset();
    item->assigned((executed= 0));
  }
这里如果已经执行过的子查询不可缓存则不缓存结果.这里的uncacheable取值为如下:

// uncachable cause
#define UNCACHEABLE_DEPENDENT   1
#define UNCACHEABLE_RAND        2
#define UNCACHEABLE_SIDEEFFECT	4
/// forcing to save JOIN for explain
#define UNCACHEABLE_EXPLAIN     8
/* For uncorrelated SELECT in an UNION with some correlated SELECTs */
#define UNCACHEABLE_UNITED     16
#define UNCACHEABLE_CHECKOPTION 32

这里UNCACHEABLE_DEPENDENT明显在说明dependent子查询计划是不可缓存的,

其它几个类型不清楚啥作用.在调试select * from a where a > all(select * from b)时发

现select * from b 这个子查询的优化发生在其具体执行的时候,这倒是和postgresql不同,

postgresql在执行计划前完成了所有节点的计划与优化.另外对于子查询中存在group这

种语句时postgresql不能提升子查询但是mysql却可以,mysql会将父节点的结果存入一

个join buffer,然后和子查询做连接而不像postgresql那样对于nest loop join先外节点后

内节点的扫描.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值