如果根据EXPLAIN QUERY PLAN,为什么SQL查询比另一个慢?它应该相反?

时间:2013-07-18 23:46:20

标签: sql performance sqlite sql-execution-plan

我有两张桌子

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运行两个代码时,

  • 第1次需要0秒
  • 第二次需要0.3281秒

为什么?

3 个答案:

答案 0 :(得分:6)

我会指出这两个查询不相同。

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

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

对于第二个查询,SQLite在Id列上创建临时索引(这是AUTOMATIC的含义)。 您应该明确地创建此索引。