【问题标题】:Why a SQL query is slower than another if according to EXPLAIN QUERY PLAN it should be the opposite?如果根据 EXPLAIN QUERY PLAN 它应该是相反的,为什么一个 SQL 查询比另一个慢?
【发布时间】:2013-07-18 03:15:30
【问题描述】:

我有两张桌子

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 秒

为什么??

【问题讨论】:

    标签: sql performance sqlite sql-execution-plan


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-13
          • 2016-12-16
          • 2017-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多