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 1explain
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列上的范围进行分区的。当我运行第一个查询时,它是通过分区修剪完成的,而在第二个查询中,它访问了所有分区。
任何人请给我线索,我环顾四周,还不知道发生了什么事,谢谢:)
发布于 2016-11-01 22:20:21
决定执行计划(包括不需要哪些分区)的优化器在从表读取实际数据之前运行。
第一个查询将子查询限制在常量值ip_start和134744072之间的特定范围内,因此可以清楚地看到数据在哪个分区中。(顺便说一句:您必须确保子查询返回最大值。一行,否则会导致错误)。
对于第二个查询,优化器在启动之前无法知道所需的范围。它将依赖于在读取event表时找到的数据。这就是为什么这个查询的select_type是一个dependent subquery,而对于第一个查询,它是一个subquery (因此是一个独立于event表的固定结果集)。所以优化器还不能排除一个分区,所以它会列出所有的分区。当查询执行时,它将读取第一行,现在它知道ip_src的值是134744072,因此ip_start-range和数据所在的分区,所以MySQL现在将在正确的分区中查找它。
实际上,这两个查询都只从该分区读取,但对于第一个分区,MySQL知道在开始之前,第二个分区不读取。
最后是一个警告:看起来您正在尝试使用分区来加快查询速度。这不是分区的用途!索引用于这一目的。对于limit 1来说,这并没有什么区别,但是如果您查询更多的行,每个分区就像一个独立的表(基本上是这样),因此,MySQL不必在一个索引中查找数据(一个较大的表,但大小基本上不重要),而是必须在30到40个不同的分区(=表)中查找数据,所有这些分区都有自己的索引、文件和结构。这通常比不使用分区要慢(而且几乎永远不会更快)。600 k行可能已经足够至少看到一个小的效果,所以在不进行分区的情况下进行测试。
https://stackoverflow.com/questions/40365988
复制相似问题