4

我有一个看起来像这样的查询:

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 是索引列(主键)。如果我用这一行返回的 int1/int2 的值替换t.int1and ,查询将在毫秒内完成。t.int2如果我按上述方式执行查询——即引用int1/int2,大约需要10 分钟。当我运行分析器并查看实际发生的情况时,我发现 99% 的时间引擎都忙于从内联查询返回数据。看起来好像 MySql 实际上正在运行

select ... from big_table_with_millions_of_rows 

在应用之前的内联查询的位

where id between t.int1 and t.int2

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

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

4

3 回答 3

1

如果可以,尽量使用 JOIN 来避免相关子查询。

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

于 2009-12-11T22:02:54.840 回答
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。他们在每个版本中改进了优化器,因此您可能会使用更新的版本获得更好的结果。

于 2009-12-12T06:00:28.717 回答
0

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

于 2009-12-11T20:19:29.373 回答