Mysql分区修剪不能在我的子查询上工作

时间:2016-11-01 18:08:16

标签: mysql subquery partition pruning

explain 
SELECT
    ip_src,
    (SELECT country FROM ip_location WHERE ip_start between (134744072-500000) and (134744072) and ip_end > 134744072) country_src,
    ip_dst
FROM
    event e
WHERE 
    long_date BETWEEN '2016-03-25 00:00:00' AND '2016-03-25 23:59:59'
LIMIT 1

partition pruning working

explain
SELECT
    ip_src,
    (SELECT country FROM ip_location WHERE ip_start between (ip_src-500000) and (ip_src) and ip_end > ip_src) country_src,
    ip_dst
FROM
    event e
WHERE 
    long_date BETWEEN '2016-03-25 00:00:00' AND '2016-03-25 23:59:59'
LIMIT 1

partition pruning not working

我有2个查询, ip_src值为134744072。

我的Ip_location表按ip_start列上的范围分区。 当我运行第一个查询时,它完成了分区修剪,但在第二个查询中它访问了所有分区。

任何人都请给我线索,我已经四处寻找n不知道发生了什么事,以前谢谢你。)

1 个答案:

答案 0 :(得分:0)

决定执行计划的优化器,包括它不需要的分区,在从表中读取实际数据之前运行。

您的第一个查询将子查询限制在常量值ip_start134744072-500000之间134744072的特定范围,因此很清楚数据所在的分区。(顺便说一句:你必须确保子查询返回最多一行,否则会导致错误。)

对于第二个查询,优化程序在启动之前无法知道所需的范围。它将取决于它在读取event表时找到的数据。这就是为什么此查询的select_typedependent subquery,而对于第一个查询,它是subquery(所以固定的结果集独立于event表)。因此优化器还不能排除分区,所以它会列出所有分区。当执行查询时,它将读取第一行,现在知道ip_src的值是134744072,因此知道ip_start - 范围和数据所在的分区,以及所以MySQL现在会在正确的分区中查找它。

两个查询实际上只会从那个分区中读取,但对于第一个分区,MySQL知道在它开始之前,对于第二个分区,它不会。

最后一个警告:看起来您正在尝试使用分区来加速查询。这不是分区的用途!索引用于此。对于limit 1,它没有什么区别,但如果你查询更多的行,每个分区将像一个独立的表(它基本上是),所以而不是在1个索引中查找数据(更大的表)但是,当你有索引时,大小基本无关紧要),MySQL必须在30个,40个不同的分区(=表)中查找数据,所有分区都有自己的索引,文件和结构。这通常比不使用分区更慢(并且几乎从不更快)。 600k行可能已经足以看到至少一个小的影响,所以在没有分区的情况下进行测试。