【问题标题】:Efficient variant record selection in sqlite / JOIN with OR terms在 sqlite / JOIN 中使用 OR 术语进行有效的变体记录选择
【发布时间】:2012-10-17 17:45:29
【问题描述】:

我有一个使用 sqlite3 的数据记录应用程序来存储共享一个公共标头的不同类型的记录。

我将标题放在一个表中,并为每个变体的详细信息创建了单独的表。

明细表中的rowid是表头的rowid。标题 rowid 仅显示在其中一个详细信息表中(针对该变体)。

我想在单个查询中获取多种类型的记录。 也就是说,我希望 Sqlite 对 headers 表进行索引搜索以找到一组工作记录,然后使用该组 ids 通过 rowid 对变体详细信息进行快速二进制获取。所以:

SELECT * FROM headers JOIN headers 
ON headers.id = variant1.id OR headers.id = variant2.id
WHERE some_header_condition

SELECT * FROM headers JOIN headers
ON headers.id IN (variant1.id, revariant2.id )
WHERE some_header_condition

这可行,但是当遇到 JOIN 谓词中的 OR 项时,sqlite3 会对详细信息表 variant1 和 variant2 进行全表扫描,而不是仅通过 rowid 外键获取适当的记录。

类似:

0     0              2     SCAN TABLE variant2 (~5900 rows)
0     1              1     SCAN TABLE variant1 (~26588 rows)
0     2              0     SEARCH TABLE headers USING INTEGER PRIMARY KEY (rowid=?) (~2 rows)
0     0              0     EXECUTE LIST SUBQUERY 1

我可以通过以下技巧强制二进制搜索:

SELECT header.f1, variant1.f, NULL FROM header JOIN header.id = variant1.id ...
UNION ALL
SELECT header.f1, NULL, variant2.f FROM header JOIN header.id = variant2.id ...

但是随后头表被访问了两次。

我还可以想象将 header.id(s) 选择到一个临时表中,并使用其中的 id 来获取详细信息。

或者...我可以将整个混乱状态反规范化。

但是所有这些变通方法都非常不方便。所以我的问题是,是否有一个不错的 JOIN 查询可以一次性获取这些变体而无需表扫描?

【问题讨论】:

    标签: sql join sqlite


    【解决方案1】:

    尝试使用外连接:

    SELECT *
    FROM headers
      LEFT JOIN variant1 ON headers.id = variant1.id
      LEFT JOIN variant2 ON headers.id = variant2.id
    WHERE headers...
    

    导致这样的计划:

    sele  order  from  deta
    ----  -----  ----  ----
    0     0      0     SEARCH TABLE headers USING INTEGER PRIMARY KEY (rowid>? AND rowid<?) (~31250 rows)
    0     1      1     SEARCH TABLE variant1 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
    0     2      2     SEARCH TABLE variant2 USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
    

    【讨论】:

    • 完美。谢谢。我想我尝试过 LEFT JOINS,但我从未尝试将多个 LEFT JOIN 链接在一起以摆脱 OR 术语。 (似乎大多数示例从不超过 2 个表!)这种语法仍然感觉有点陌生,但效果很好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多