MySql和内联SELECT

时间:2009-12-11 20:08:11

标签: sql mysql inline explain

我有一个如下所示的查询:

select
id
, int1
, int2
, (select count(*) from big_table_with_millions_of_rows 
    where id between t.int1 and t.int2)
from myTable t
where
....

此选择只返回一行。内联选择中使用的id是索引列(主键)。如果我将t.int1t.int2替换为此单行返回的int1 / int2的值,则查询以毫秒为单位完成。如果我执行上面的查询 - 即引用int1 / int2,大约需要10分钟。当我运行探查器并查看实际发生的情况时,我发现99%的时间引擎忙于从内联查询返回数据。看起来MySql实际上正在运行

select ... from big_table_with_millions_of_rows 
在应用

之前,

一次内联查询

where id between t.int1 and t.int2

指向结果。这可能是真的吗?如果没有,那么发生了什么?我一直认为内联SELECT具有潜在的危险性,因为它们作为查询的最后一个元素逐行执行,但对于这样的情况,初始SELECT确实是高度选择性的,它可以非常有效。任何人都可以对此有所了解吗?

编辑:感谢您的反馈。我关心的不是内联查询的逐行性质,而是面对变量而不是(相同的)硬编码值时似乎无法使用主键索引的事实。我的猜测是,如果最近没有运行ANALYZE,那么优化器会假设它必须进行表扫描,因为它不知道数据分布。但是不应该在主键上完成范围查找这一事实不能弥补这一点吗?

3 个答案:

答案 0 :(得分:1)

如果可以,请尝试使用JOIN来避免相关子查询。

youtube上观看有关MySQL性能的精彩视频。转到31:00分钟。演讲者Jay Pipes谈论避免相关的子查询。

答案 1 :(得分:1)

如果相关子查询未得到很好的优化,请尝试以下查询:

select
  t.id
, t.int1
, t.int2
, count(*)
from myTable t
left outer join big_table_with_millions_of_rows b
  on (b.id between t.int1 and t.int2)
where
....
group by t.id

这应该更好地优化。


重新提出更新的问题:对,MySQL在优化方面不是市场上最复杂的RDBMS。当MySQL无法优化像这样的角落情况时,不要感到惊讶。

我是MySQL的粉丝,因为它的易用性和开源以及所有这些好东西,但事实是它的竞争对手在技术方面远远领先于MySQL。每个RDBMS都有一些“盲点”,但MySQL看起来更大。

还要确保您使用的是最新版本的MySQL。他们在每个版本中都改进了优化器,因此使用较新版本可能会获得更好的结果。

答案 2 :(得分:0)

如果子查询引用其包含查询的字段,则必须根据包含查询中的每一行重新运行子查询,因为每行中引用的字段可能不同。如果它完全是自包含的,则可以在外部查询开始处理之前运行一次。