0
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

分区修剪工作

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

分区修剪不起作用

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

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

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

4

1 回答 1

0

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

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

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

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

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

于 2016-11-01T22:20:21.210 回答