【问题标题】:WHERE clause followed by JOINWHERE 子句后跟 JOIN
【发布时间】:2013-08-02 17:59:52
【问题描述】:

我有一个非常大的值表。我们称该表为big。我有一张小一点的桌子,叫做small。我想加入这些表格,但仅限于 big 中的特定值。

我可以通过说得到值

SELECT a,b FROM big WHERE foo='bar';

我想用small 加入这个结果,说如下:

SELECT a,b FROM big WHERE foo='bar' 
LEFT JOIN (SELECT b as small_b,c,d FROM small) ON big.b=small.small_b

我不想把所有东西都放在big 中,因为那是很多东西,而且需要半分钟。我只需要那个小子集。我该怎么做呢?

编辑:我已编辑查询以匹配末尾的 WHERE 子句。尽管我将其中一张表称为big,但它实际上有不到 500,000 行。我使用的测试用例查询没有使用在big 中找到的任何值(big 在 foo='bar' 处没有值),并且查询仍然花费了 7 多秒。这真的很正常吗?这对我来说似乎非常慢。

【问题讨论】:

    标签: mysql sql join where


    【解决方案1】:

    我认为您将 SQL 的语法误认为是 RDBMS 引擎执行的执行流程:这个查询

    SELECT a,b FROM big b
    LEFT JOIN (SELECT b as small_b,c,d FROM small) ON big.b=small.small_b
    WHERE b.foo='bar'
    

    将被优化为仅对由foo='bar' 条件过滤的big 行执行连接,而不是在整个big 上,由任何值得其盐的查询优化器执行,尽管@ 987654325@ 子句以文本形式出现在JOIN 之后。

    您可能想在没有内部SELECT 的情况下重写它,如下所示:

    SELECT t1.a as big_a, t1.b as big_b, t2.b as small_b, t2.c, t2.d
    FROM big t1
    LEFT JOIN small t2 ON t1.b = t2.b
    WHERE t1.foo='bar'
    

    【讨论】:

    • 您是否有机会更新您对我的编辑的回复?我知道我不应该那样改变问题,但我想弄清楚为什么它这么慢......
    • @MirroredFate 我假设您在foo 上有一个索引,对吧?否则,将是一次全表扫描,以查看要对任何行进行联接。
    • 我以为我做到了。我刚刚检查过,显然我只有 foo 作为唯一键的一部分......所以我开始为 foo 开始索引操作,它仍在运行......这应该会有所帮助。假设一切正常,我会告诉你索引操作后查询需要多长时间。
    • Mk,不幸的是,查询现在需要 9 到 20 秒。
    • @MirroredFate 在添加索引后查询SELECT a,b FROM big b WHERE foo='bar' 需要多长时间?它应该几乎是瞬时的。
    【解决方案2】:

    稍微简化一下,WHERE 子句不能放在JOIN 之前,它需要按照语法规则放在它后面。优化器会计算出最佳的执行顺序,并且不一定按照您列出的顺序执行。

    SELECT big.a, big.b, small.b as small_b, small.c, small.d 
    FROM big 
    LEFT JOIN small
      ON big.b = small.b
    WHERE foo = 'bar';
    

    编辑:如果查询很慢,没有命中或命中最少,可能的原因是foo 上缺少索引。

    foobig.bsmall.b 上添加索引,您应该会看到加速。

    【讨论】:

      猜你喜欢
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多