代码之家  ›  专栏  ›  技术社区  ›  davek

mysql和inline选择

  •  4
  • davek  · 技术社区  · 15 年前

    我有一个查询如下所示:

    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具有潜在的危险性,因为它们作为查询的最后一个元素逐行执行,但是对于这样的情况,其中 选择 确实是高度选择性的,它可以非常有效。有人能解释一下吗?

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

    3 回复  |  直到 14 年前
        1
  •  1
  •   Bill Karwin    15 年前

    如果相关子查询没有很好地优化,请尝试此查询:

    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
  •  1
  •   Yada    15 年前

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

    观看有关mysql性能的精彩视频 youtube . 到31:00分。演讲者JayPipes谈到了避免相关子查询。

        3
  •  0
  •   Dewayne Christensen    15 年前

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