2011-08-09 30 views
6

Tôi đang làm việc để tạo báo cáo cho dữ liệu chứa trong cơ sở dữ liệu Access trước lớn (~ 500 mb sau khi sửa chữa nhỏ gọn &) và tôi gặp sự cố với truy vấn con chậm .Truy vấn phụ rất chậm khi sử dụng "KHÔNG IN"

Cơ sở dữ liệu có bảng lớn chứa bản ghi về mọi giao dịch mua của khách hàng. Đây là một truy vấn đơn giản tìm thấy những khách hàng đã mua một tiện ích màu xanh lam. Nó hoàn thành trong vòng vài giây và trả về khoảng mười nghìn bản ghi.

SELECT DISTINCT CustomerId 
FROM ProductSales 
WHERE Product = 'BLUE' 

Đây là truy vấn cố gắng tìm khách hàng đã mua tiện ích con màu xanh, chứ không phải tiện ích con màu đỏ. Phải mất khoảng một giờ để chạy.

SELECT DISTINCT CustomerId FROM ProductSales 
WHERE Product = 'BLUE' 
AND CustomerId NOT IN (
    SELECT CustomerId 
    FROM ProductSales 
    WHERE Product = 'RED' 
) 

Có cách nào để cấu trúc lại truy vấn thứ hai để mất vài phút thay vì một giờ không?

+0

Tôi giả sử trường CustomerId có chỉ mục trên nó trong cả hai bảng? –

+0

Bạn đã thử SELECT DISTINCT CustomerId FROM ProductSales WHERE Product = 'BLUE' trừ SELECT CustomerId FROM ProductSales WHERE Product = 'RED'. Tôi đã nhìn thấy các trường hợp nó thực sự đẩy nhanh truy vấn, nhưng YMMV –

+0

@Marc B: Chỉ có một bảng ở đây, nhưng CustomerId được lập chỉ mục trên đó. – James

Trả lời

10

Cơ sở dữ liệu truy cập 'không thể sử dụng chỉ mục cho Not In, vì vậy nó bị ràng buộc chậm. Với chỉ mục trên CustomerId, truy vấn này sẽ nhanh hơn nhiều vì công cụ db có thể sử dụng chỉ mục.

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; 

Bạn cũng có thể thử cách tiếp cận Not Exists, nhưng việc sử dụng chỉ mục không được đảm bảo. Ngoài ra, xin vui lòng xem bình luận dưới đây từ David Fenton mà thảo luận về tác động hiệu suất chi tiết hơn.

+1

Woah. Giảm từ 60 phút xuống còn khoảng một giây. Nhanh hơn 3600 lần so với phiên bản cũ. Cảm ơn! :-) Để tham khảo trong tương lai, có danh sách các hoạt động SQL Access không sử dụng chỉ mục cho một nơi nào đó không? – James

+1

Có lẽ có một danh sách ở đâu đó, nhưng tôi không biết ở đâu. :-) Nếu bạn muốn tìm hiểu về điều này, Google Jet ShowPlan ... sẽ cho bạn biết cách tác giả/nếu động cơ db đang sử dụng các chỉ mục với truy vấn của bạn. Bạn có thể tìm thấy thảo luận chi tiết về hiệu suất truy vấn tại đây: http://msdn.microsoft.com/en-us/library/aa188211 (office.10).aspx – HansUp

+1

Nó không phải là NOT IN và NOT EXISTS không bao giờ sử dụng các chỉ mục - nó mà bạn không thể dự đoán được khi nào họ sẽ và khi nào họ sẽ không. Bất cứ lúc nào bạn có thể tái thiết kế một truy vấn con KHÔNG IN/EXISTS thành JOIN, bạn có thể cải thiện hiệu suất. Tuy nhiên, tất cả phụ thuộc vào khả năng chỉnh sửa của recordset kết quả - một số truy vấn phụ được sử dụng trong JOIN sẽ làm cho truy vấn không thể cập nhật được. –

0

Thêm chỉ mục, tất nhiên, nếu bạn chưa có. Nếu đó là một vấn đề, nó có lẽ chỉ là có rất nhiều khách hàng với đơn đặt hàng cho một cái gì đó khác hơn so với RED nhưng không quá nhiều với BLUE; truy vấn này (chưa được kiểm tra) cố gắng sửa lỗi đó.

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 
Các vấn đề liên quan