我正在为大型预先存在的Access数据库中包含的数据生成报告(紧凑和修复后约500 MB),而我遇到了一个慢速子查询的问题。
数据库有一个大表,其中包含每个客户购买的记录。这是一个简单的查询,可以找到购买蓝色小部件的客户。它在几秒钟内完成并返回大约一万条记录。
SELECT DISTINCT CustomerId
FROM ProductSales
WHERE Product = 'BLUE'
这是一个查询,它试图找到购买蓝色小部件但不是红色小部件的客户。运行大约需要一个小时。
SELECT DISTINCT CustomerId FROM ProductSales
WHERE Product = 'BLUE'
AND CustomerId NOT IN (
SELECT CustomerId
FROM ProductSales
WHERE Product = 'RED'
)
有没有办法重构第二个查询,使其花费几分钟而不是一小时?
答案 0 :(得分:11)
Access'数据库引擎不能使用Not In
的索引,所以它一定很慢。使用CustomerId上的索引,此查询应该更快,因为数据库引擎可以使用索引。
SELECT DISTINCT blue.CustomerId
FROM
ProductSales AS blue
LEFT JOIN
(
SELECT CustomerId
FROM ProductSales
WHERE Product = 'RED'
) AS red
ON blue.CustomerId = red.CustomerId
WHERE
blue.Product = 'BLUE'
AND red.CustomerId Is Null;
您可能也可以尝试Not Exists
方法,但无法保证索引的使用。另外,请参阅下面David Fenton的评论,其中更详细地讨论了性能影响。
答案 1 :(得分:0)
当然,如果您没有索引,请添加索引。如果这是一个问题,可能只是有很多客户订购RED以外的其他东西而不是BLUE那么多;这个(未经测试的)查询试图修复它。
SELECT DISTINCT CustomerId FROM ProductSales
LEFT JOIN (
SELECT DISTINCT CustomerId cid FROM ProductSales
LEFT JOIN (
SELECT DISTINCT CustomerId
FROM ProductSales
WHERE Product = 'BLUE'
) foo ON CustomerId = cid
WHERE Product = 'RED'
) bar USING (CustomerId)
WHERE cid IS NULL