1

我有两张桌子

CREATE TABLE Categories (
   Category INTEGER,
   Id INTEGER,
   FOREIGN KEY (Category) REFERENCES CategoriesInfo(Category)
)
CREATE TABLE 'CategoriesInfo' (
   'Category' INTEGER PRIMARY KEY NOT NULL,
   'Name' TEXT
)

带索引

CREATE UNIQUE INDEX idxCategory ON Categories (Category, Id)

如果我跑

EXPLAIN QUERY PLAN
SELECT CategoriesInfo.Category, Name
FROM Categories, CategoriesInfo
Where Categories.Category=CategoriesInfo.Category AND Id=:id
ORDER BY Name

它说

Array
(
    [0] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 1
            [detail] => SCAN TABLE CategoriesInfo (~1475 rows)
        )

    [1] => Array
        (
            [selectid] => 0
            [order] => 1
            [from] => 0
            [detail] => SEARCH TABLE Categories USING COVERING INDEX idxCategory (Category=? AND Id=?) (~1 rows)
        )

    [2] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => USE TEMP B-TREE FOR ORDER BY
        )

)

但是如果我使用连接

EXPLAIN QUERY PLAN
SELECT CategoriesInfo.Category, CategoriesInfo.Name
FROM Categories
LEFT JOIN CategoriesInfo ON (Categories.Category=CategoriesInfo.Category)
WHERE Categories.Id=:id
ORDER BY Name

我明白了

Array
(
    [0] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => SEARCH TABLE Categories USING AUTOMATIC COVERING INDEX (Id=?) (~6 rows)
        )

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

    [2] => Array
        (
            [selectid] => 0
            [order] => 0
            [from] => 0
            [detail] => USE TEMP B-TREE FOR ORDER BY
        )

)

然后,使用连接应该更快。但是当我用 phpliteadmin 运行这两个代码时,

  • 第一个需要 0 秒
  • 第二次耗时 0.3281 秒

为什么??

4

3 回答 3

6

我会指出这两个查询是不等价的。

您的第一个查询有效地执行了 INNER JOIN,而您的第二个查询是 LEFT JOIN。我敢打赌这是速度差异的原因。您的 LEFT JOIN 将要求输出中包含类别中的所有记录,这是您的第一个查询不需要的。

尝试将 LEFT JOIN 更改为 INNER JOIN,然后比较速度。

于 2013-07-18T23:53:41.003 回答
0

解释计划的一个常见误解是它们给出了查询性能的现实期望。然而,他们所做的是为您提供对数据库认为运行查询所需的良好估计。这取决于许多因素,例如表索引、查询中涉及的表的统计信息、并行度以及为系统分配的总体资源。

于 2013-07-19T00:04:41.397 回答
0

对于第二个查询,SQLite 在Id列上创建一个临时索引(这就是AUTOMATIC意思)。您应该显式创建此索引。

于 2013-07-19T07:31:38.457 回答