使用"NOT IN"时非常慢的子查询

Jam*_*mes 7 ms-access query-optimization

我正在为大型预先存在的Access数据库中包含的数据生成报告(紧凑和修复后约500 MB),我遇到了一个慢速子查询的问题.

数据库有一个大表,其中包含每个客户购买的记录.这是一个简单的查询,可以找到购买蓝色小部件的客户.它在几秒钟内完成并返回大约一万条记录.

SELECT DISTINCT CustomerId 
FROM ProductSales
WHERE Product = 'BLUE' 
Run Code Online (Sandbox Code Playgroud)

这是一个查询,试图找到已经购买蓝色小部件但不是红色小部件的客户.运行大约需要一个小时.

SELECT DISTINCT CustomerId FROM ProductSales
WHERE Product = 'BLUE' 
AND CustomerId NOT IN (
    SELECT CustomerId 
    FROM ProductSales 
    WHERE Product = 'RED'
)
Run Code Online (Sandbox Code Playgroud)

有没有办法重构第二个查询,使其花费几分钟而不是一个小时?

Han*_*sUp 11

访问'数据库引擎无法使用索引Not In,因此它必然会很慢.使用CustomerId上的索引,此查询应该快得多,因为db引擎可以使用索引.

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; 
Run Code Online (Sandbox Code Playgroud)

您可能也可以尝试一种Not Exists方法,但索引使用并不能保证.另外,请参阅下面David Fenton的评论,其中更详细地讨论了性能影响.