1

我有一个大小约为 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")
)

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

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

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,这可能是原因吗?

4

1 回答 1

0

如果您将其重写为 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 版本,子查询只评估一次,并且根据需要重用结果。

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

于 2014-02-20T12:29:03.227 回答