我有一个大约3GB的SQLite3数据库,我试图查询它以便在两个日期之间显示特定产品的最新订单。
以下是用于创建表的查询:
CREATE TABLE "ProductOrders" (
"ID" INTEGER NOT NULL UNIQUE,
"ProductID" INTEGER NOT NULL,
"AdditionalInfo" TEXT,
"OrderDateTime" DOUBLE NOT NULL,
PRIMARY KEY ("ProductID", "OrderDateTime")
)
我在ProductID
和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,这可能是一个原因吗?
答案 0 :(得分: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版本,子查询仅计算一次,结果将被重用有必要的。
在这种情况下,因为您的外部查询非常宽(整个表)并且您的子查询要窄得多(按日期过滤),所以如果您的外部查询非常狭窄(即仅预期到返回几行),然后相关的子查询版本会更好,因为当只需要几个结果时,对所有值执行子查询都没有用。