Mysql 分区修剪不适用于我的子查询

Mysql Partition pruning not working on my subquery

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 table 在 ip_start 列上按范围分区。 当我 运行 第一次查询时,它完成了分区 p运行ing,但在第二次查询中它访问了所有分区。

任何人请给我线索,我环顾四周但不知道发生了什么事,先谢谢你:)

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

您的第一个查询将您的子查询限制在常数值 134744072-500000134744072 之间的 ip_start 的特定范围内,因此很清楚数据位于哪个分区。(顺便说一句.: 你必须确保子查询 returns 最多一行,否则会导致错误。

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

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

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