【问题标题】:Optimizing a two-level SQL query优化两级 SQL 查询
【发布时间】:2015-08-12 20:53:30
【问题描述】:

这是我的数据库相关部分的布局:

(顺便说一句,我用wwwsqldesigner制作了这张图)

现在,我想查询与 A 的特定行匹配的 C 的所有行。

我自己提出的查询有效。例如,在 C 中查找与 A 的第 123 行匹配的行:

SELECT C.* FROM C
LEFT JOIN B1 ON (B1.id = C.id_B1)
LEFT JOIN B2 ON (B2.id = C.id_B2)
WHERE B1.id_A = 123 OR B2.id_A = 123

但是,我认为上面的查询效率相当低,因为它会在一个大集合中收集 B1 和 B2 的所有行,然后再将其减少,对吧?

我相信我应该能够首先对 B1 和 B2 分别进行查询,选择它们的 id_A 值,然后以某种方式将这些结果连接到匹配的 C 行中。

我查看了sqlite.org's docs 的 SELECT 命令,但可能性让我不知所措。

如何解决这个问题?稍微解释一下解决这个问题的思考过程将不胜感激。

(另外,如果您可以为这个问题建议一个更好的标题 - 我真的不知道如何确定这一点)

【问题讨论】:

    标签: sql sqlite


    【解决方案1】:

    你的方法很好,虽然它看起来可能会返回重复项。

    您可能会看看其中一个是否更快:

    SELECT  C.*
    FROM C
    WHERE EXISTS (SELECT 1 FROM B1 WHERE B1.id = C.id_B1 AND B1.id_A = 123) OR
          EXISTS (SELECT 1 FROM B2 WHERE B2.id = C.id_B2 AND B2.id_A = 123);
    

    这对索引最有效。 “B”表中的id 索引很好,虽然(id, id_A) 会更好。

    或者:

    SELECT DISTINCT C.*
    FROM C JOIN
         B1 ON B1.id = C.id_B1
    WHERE B1.id_A = 123 
    UNION
    SELECT DISTINCT C.*
    FROM C JOIN
         B2 ON B1.id = C.id_B2
    WHERE B2.id_A = 123;
    

    如果您知道没有重复项,请使用 union all 而不是 union

    【讨论】:

    • 啊,是的,我在查询的末尾添加了一个GROUP BY C.id。我发现我也可以通过使用“SELECT DISTINCT C.*”来避免欺骗,但看起来这比 GROUP BY 方式要慢。谢谢你的两个例子。 UNION 很有帮助,但我认为第一个例子是最好的。我最终也会添加索引。不过,我还是想先学习如何正确处理这些查询。
    【解决方案2】:

    我认为上面的查询效率相当低,因为它在一个大集合中收集了 B1 和 B2 的所有行,然后再次减少它,对吧?

    我对 SQLite 可能是错误的,但是任何值得一提的数据库引擎都应该能够通过在 B1B2 中找到与您的 where 子句匹配的行来优化查询,所以不,它不会将整个表加载到内存中。

    您可以通过在查询前加上EXPLAIN QUERY PLAN 来查看查询使用的计划。只要引擎不在B1 和/或B2 上执行扫描表,那么查询应该没问题。

    请注意,您可以通过在B1.id_AB2.id_A 上添加索引来显着提高此查询的性能

    【讨论】:

    • “解释查询计划”提示很棒。这至少可以帮助我验证我是否有效率。如果它效率低下,我现在仍然不得不在这里寻求帮助:)
    • 当我正确阅读了 SELECT 命令的 sqlite 文档时,只有在执行 JOIN 之后才会处理 WHERE 部分。我还觉得这个结构的查询需要很长时间。
    • @ThomasTempelmann 我无论如何都不是 SQLite 专家,所以我不能说这个。但是,如果引擎在过滤之前将所有数据加载到内存中(这就是您所暗示的),我会感到惊讶。我怀疑它使用索引或其他方式仅加载必要的数据。
    猜你喜欢
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    • 2014-02-04
    • 2014-11-16
    • 2011-06-22
    相关资源
    最近更新 更多