MySql和内联选择

MySql和内联选择,sql,mysql,inline,explain,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.int1和t.int2替换为这一行返回的int1/int2值,查询将在毫秒内完成。如果我像上面那样执行查询,即引用

我有一个如下的查询:

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.int1
t.int2
替换为这一行返回的int1/int2值,查询将在毫秒内完成。如果我像上面那样执行查询,即引用int1/int2,大约需要10分钟。当我运行profiler并查看实际发生的情况时,我看到99%的时间引擎都在忙于从内联查询返回数据。看起来MySql实际上正在运行

select ... from big_table_with_millions_of_rows 
在应用

where id between t.int1 and t.int2
结果有点不妙。这是真的吗?如果没有,那是怎么回事?我一直认为内联
SELECT
s有潜在的危险,因为它们是作为查询的最后一个元素逐行执行的,但是对于这样的情况,初始
SELECT
确实是高度选择性的,它可以非常有效。有人能解释一下吗


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

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

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


观看这段关于MySQL性能的精彩视频。一分钟后到31点。演讲者Jay Pipes谈到避免相关子查询。

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

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的易用性、开源以及所有这些优点,但事实是,它的竞争对手在技术上远远领先于MySQL。每个RDBMS都有一些“盲点”,但MySQL似乎更大


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

+1谢谢:这将执行时间从几分钟缩短到几秒钟。我以后一定要记住这一点!