3

我读过联接比子查询更好。

EXPLAIN QUERY PLAN
SELECT Queue.Id, NULL
    FROM Queue
    INNER JOIN LastQueue
    ON Queue.Id=LastQueue.Id

Array
(
    [0] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => SCAN TABLE Queue (~1000000 rows)
        )

    [1] => Array
        (
            [selectid] => 0
            [order] => 1
            [from] => 1
            [detail] => SEARCH TABLE LastQueue USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
        )

)

尽管

EXPLAIN QUERY PLAN
SELECT Queue.Id, NULL
    FROM Queue
    WHERE (SELECT 1 FROM LastQueue WHERE Queue.Id=LastQueue.Id) IS NOT NULL

Array
(
    [0] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => SCAN TABLE Queue (~500000 rows)
        )

    [1] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => EXECUTE CORRELATED SCALAR SUBQUERY 1
        )

    [2] => Array
        (
            [selectid] => 1
            [order] => 0
            [from] => 0
            [detail] => SEARCH TABLE LastQueue USING INTEGER PRIMARY KEY (rowid=?) (~1 rows)
        )

)

我想我必须乘以行数才能了解成本。我是对的?

然后,

  • 使用连接:1000000*1
  • 使用子查询:500000*1*1

那么,子查询是不是比join快呢?

有没有很好的教程来学习如何理解EXPLAIN/EXPLAIN QUERY PLAN结果?

当该表有 76 行时,为什么它说 SCAN TABLE Queue 为 ~1000000 和 ~500000?

4

2 回答 2

8

该行EXECUTE CORRELATED SCALAR SUBQUERY 1就在那里,因为您使用的是不同的查询语法。

两种情况的实际执行是一样的:SQLite 遍历表的所有记录Queue,并尝试在表中查找相应的记录LastQueue

估计的记录数不同与您无关,因为您知道实际的记录数是相同的。

联接可能比其他数据库中的子查询更好,但在仅使用嵌套循环联接的 SQLite 中,唯一的区别是联接允许 SQLite 在联接中选择外部表和内部表。

在任何情况下,您都应该以最简单和可维护的方式编写查询,并且只有在您测量到您获得了显着且必要的改进时才对其进行优化。


请注意,而不是:

WHERE (SELECT ...) IS NOT NULL

写起来会更惯用:

WHERE EXISTS (SELECT ...)
于 2013-07-16T06:51:35.060 回答
1

解释为您的表格提供了不准确的计数。尝试使用分析来收集表上的统计信息,然后再次尝试解释。

我想你会发现这两个查询将以几乎完全相同的速度返回。由于额外的步骤,子查询可能较慢。这里要注意的重要一点是“SCAN TABLE”,这意味着它正在查看磁盘上的所有行。

http://www.sqlite.org/lang_analyze.html

还有可能你的表上没有索引吗?因为它应该使用它们,但它似乎不是。确保在 create table 语句中使用主键。

http://www.sqlite.org/lang_createtable.html

于 2013-07-15T20:37:55.367 回答