【问题标题】:Retrieving latest datetime for each product检索每个产品的最新日期时间
【发布时间】:2014-02-20 12:20:30
【问题描述】:

我有一个大小约为 3GB 的 SQLite3 数据库,我正在尝试查询它,以便在 2 个日期之间调出特定产品的最新订单。

这是用于创建表的查询:

CREATE TABLE "ProductOrders" (
    "ID" INTEGER NOT NULL  UNIQUE,
    "ProductID" INTEGER NOT NULL,
    "AdditionalInfo" TEXT,
    "OrderDateTime" DOUBLE NOT NULL,
    PRIMARY KEY ("ProductID", "OrderDateTime")
)

我在ProductIDOrderDateTime 上创建了索引,以确保表中没有重复项。

我目前用于执行此操作的查询如下:

Select ProductID, AdditionalInfo, OrderDateTime
  From ProductOrders a
  Where a.OrderDateTime = ( Select max(OrderDateTime)
                              From ProductOrders b
                              Where a.ProductID = b.ProductID
                                AND b.OrderDateTime < 40544.5
                                AND b.OrderDateTime > 40539.5
                          )

该查询工作正常并且完全符合我的要求,但它似乎正在扫描整个表以查找查询的“a”部分。我的踪迹如下:

0|0|0|SCAN TABLE ProductOrders AS a
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 1
1|0|0|SEARCH TABLE ProductOrders AS b USING COVERING INDEX sqlite_autoindex_ProductOrders_2 (ProductID=? AND OrderDateTime>? AND OrderDateTime<?)

运行至少需要 2 分钟,这是无法使用的。我注意到在结构中,ProductID 显示为主键 1,OrderDateTime 显示为主键 2,这可能是原因吗?

【问题讨论】:

    标签: sql sqlite max full-table-scan


    【解决方案1】:

    如果您将查询重写为 JOIN,我希望您的查询会执行得更好:

    SELECT  a.ProductID, a.AdditionalInfo, a.OrderDateTime
    FROM    ProductOrders a
            INNER JOIN
            (   SELECT  b.ProductID, MAX(b.OrderDateTime) AS OrderDateTime
                FROM    ProductOrders b
                WHERE   b.OrderDateTime < 40544.5
                AND     b.OrderDateTime > 40539.5
                GROUP BY b.ProductID
            ) b
                ON a.ProductID = b.ProductID
                AND a.OrderDateTime = b.OrderDateTime;
    

    对于相关子查询,子查询会针对ProductOrders 中的每条记录重新评估(这就是您看到全表扫描的原因),而对于 JOIN 版本,子查询只评估一次,并根据需要重用结果.

    在这种情况下,由于您的外部查询非常宽(整个表)并且您的子查询要窄得多(按日期过滤),如果您的外部查询非常窄(即只期望返回几行),那么相关子查询版本会更好,因为当只需要几个结果时,对所有值执行子查询是不利的。

    【讨论】:

    • 在这种特殊情况下,连接条件与索引匹配。
    猜你喜欢
    • 2013-08-15
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 2013-08-01
    • 2021-12-04
    • 2020-11-19
    • 2017-02-13
    相关资源
    最近更新 更多