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列上的范围分区。 当我运行第一个查询时,它完成了分区修剪,但在第二个查询中它访问了所有分区。
任何人都请给我线索,我已经四处寻找n不知道发生了什么事,以前谢谢你。)
答案 0 :(得分:0)
决定执行计划的优化器,包括它不需要的分区,在从表中读取实际数据之前运行。
您的第一个查询将子查询限制在常量值ip_start
和134744072-500000
之间134744072
的特定范围,因此很清楚数据所在的分区。(顺便说一句:你必须确保子查询返回最多一行,否则会导致错误。)
对于第二个查询,优化程序在启动之前无法知道所需的范围。它将取决于它在读取event
表时找到的数据。这就是为什么此查询的select_type
是dependent subquery
,而对于第一个查询,它是subquery
(所以固定的结果集独立于event
表)。因此优化器还不能排除分区,所以它会列出所有分区。当执行查询时,它将读取第一行,现在知道ip_src
的值是134744072
,因此知道ip_start
- 范围和数据所在的分区,以及所以MySQL现在会在正确的分区中查找它。
两个查询实际上只会从那个分区中读取,但对于第一个分区,MySQL知道在它开始之前,对于第二个分区,它不会。
最后一个警告:看起来您正在尝试使用分区来加速查询。这不是分区的用途!索引用于此。对于limit 1
,它没有什么区别,但如果你查询更多的行,每个分区将像一个独立的表(它基本上是),所以而不是在1个索引中查找数据(更大的表)但是,当你有索引时,大小基本无关紧要),MySQL必须在30个,40个不同的分区(=表)中查找数据,所有分区都有自己的索引,文件和结构。这通常比不使用分区更慢(并且几乎从不更快)。 600k行可能已经足以看到至少一个小的影响,所以在没有分区的情况下进行测试。