Làm thế nào để SQL Server biết các vị từ có tương quan?


15

Trong khi chẩn đoán các truy vấn SQL Server 2008 R2 với ước tính cardinality kém (mặc dù lập chỉ mục đơn giản, thống kê cập nhật, v.v.) và do đó các kế hoạch truy vấn kém, tôi đã tìm thấy một bài viết KB có lẽ liên quan: FIX: Hiệu suất kém khi bạn chạy truy vấn có chứa các biến vị ngữ AND tương quan trong SQL Server 2008 hoặc SQL Server 2008 R2 hoặc SQL Server 2012

Tôi có thể đoán bài viết KB có nghĩa là gì bởi "tương quan", ví dụ: vị ngữ số 2 và vị từ số 1 chủ yếu nhắm vào cùng một hàng.

Nhưng tôi không biết làm thế nào SQL Server biết về các mối tương quan này. Bảng có cần một chỉ mục nhiều cột chứa các cột từ cả hai vị từ không? SQL có sử dụng số liệu thống kê để kiểm tra xem các giá trị từ một cột có tương quan với cột khác không? Hoặc là một số phương pháp khác được sử dụng?

Tôi đang hỏi điều này vì hai lý do:

  1. để xác định bảng nào và truy vấn của tôi có thể được cải thiện bằng cách sử dụng hotfix này
  2. để biết tôi nên làm gì trong việc lập chỉ mục, thống kê, v.v. để ảnh hưởng đến # 1

Câu trả lời:


20

Hãy xem xét kế hoạch thực hiện và truy vấn AdventureWorks đơn giản dưới đây. Truy vấn chứa các vị từ được kết nối với AND. Ước tính cardinality của trình tối ưu hóa là 41.211 hàng:

-- Estimate 41,211 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

Kế hoạch thực hiện mặc định

Sử dụng số liệu thống kê mặc định

Chỉ đưa ra các thống kê cột đơn, trình tối ưu hóa tạo ra ước tính này bằng cách ước tính số lượng thẻ cho từng vị từ một cách riêng biệt và nhân các kết quả chọn lọc với nhau. Heuristic này giả định rằng các vị ngữ hoàn toàn độc lập.

Chia truy vấn thành hai phần để tính toán dễ nhìn hơn:

-- Estimate 68,336.4 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336;

Bảng Lịch sử giao dịch có tổng cộng 113.443 hàng, vì vậy ước tính 68.336,4 thể hiện độ chọn lọc là 68336.4 / 113443 = 0.60238533 cho vị từ này. Ước tính này có được bằng cách sử dụng thông tin biểu đồ cho TransactionIDcột và các giá trị không đổi được chỉ định trong truy vấn.

-- Estimate 68,413 rows
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

Vị ngữ này có độ chọn lọc ước tính là 68413.0 / 113443 = 0.60306056 . Một lần nữa, nó được tính từ các giá trị không đổi của vị từ và biểu đồ củaTransactionDate đối tượng thống kê.

Giả sử các vị từ hoàn toàn độc lập, chúng ta có thể ước tính độ chọn lọc của hai vị từ với nhau bằng cách nhân chúng với nhau. Ước tính cardinality cuối cùng thu được bằng cách nhân độ chọn lọc kết quả với 113.443 hàng trong bảng cơ sở:

0.60238533 * 0.60306056 * 113443 = 41210.987

Sau khi làm tròn, đây là ước tính 41.211 được thấy trong truy vấn ban đầu (trình tối ưu hóa cũng sử dụng toán học dấu phẩy động trong nội bộ).

Không phải là một ước tính tuyệt vời

Các cột TransactionIDTransactionDatecột có mối tương quan chặt chẽ trong tập dữ liệu AdventureWorks (vì các phím tăng đơn điệu và cột ngày thường làm). Mối tương quan này có nghĩa là giả định độc lập bị vi phạm. Kết quả là, kế hoạch truy vấn sau khi thực hiện hiển thị 68.095 hàng thay vì ước tính 41.211:

Kế hoạch hậu thực hiện

Cờ dấu vết 4137

Kích hoạt cờ theo dõi này thay đổi các heuristic được sử dụng để kết hợp các vị từ. Thay vì giả định sự độc lập hoàn toàn, trình tối ưu hóa xem xét rằng độ chọn lọc của hai vị từ đủ gần để chúng có khả năng tương quan với nhau:

-- Estimate 68,336.4
SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13'
OPTION (QUERYTRACEON 4137);

Hãy nhớ lại rằng TransactionIDvị ngữ một mình ước tính 68.336,4 hàng và TransactionDateriêng vị ngữ ước tính 68.413 hàng. Trình tối ưu hóa đã chọn mức thấp hơn của hai ước tính này thay vì nhân các mức chọn lọc.

Tất nhiên, đây chỉ là một heuristic khác, nhưng một thứ có thể giúp cải thiện các ước tính cho các truy vấn với các ANDvị từ tương quan . Mỗi vị từ được xem xét cho mối tương quan có thể có, và có những điều chỉnh khác được thực hiện khi có nhiều ANDđiều khoản liên quan, nhưng ví dụ đó phục vụ để hiển thị những điều cơ bản của nó.

Thống kê nhiều cột

Chúng có thể giúp trong các truy vấn có tương quan, nhưng thông tin biểu đồ vẫn chỉ dựa trên cột hàng đầu của thống kê. Do đó, thống kê nhiều cột của ứng viên sau đây khác nhau theo một cách quan trọng:

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionID TransactionDate]
ON Production.TransactionHistory
    (TransactionID, TransactionDate);

CREATE STATISTICS
    [stats Production.TransactionHistory TransactionDate TransactionID]
ON Production.TransactionHistory
    (TransactionDate, TransactionID);

Chỉ lấy một trong số đó, chúng ta có thể thấy rằng thông tin bổ sung duy nhất là các mức bổ sung của mật độ 'tất cả'. Biểu đồ vẫn chỉ chứa thông tin chi tiết về TransactionDatecột.

DBCC SHOW_STATISTICS
    (
        'Production.TransactionHistory', 
        'stats Production.TransactionHistory TransactionDate TransactionID'
    );

Tượng nhiều cột

Với các số liệu thống kê nhiều cột tại chỗ ...

SELECT COUNT_BIG(*)
FROM Production.TransactionHistory AS TH
WHERE 
    TH.TransactionID BETWEEN 100000 AND 168336
    AND TH.TransactionDate BETWEEN '2007-09-01' AND '2008-03-13';

... kế hoạch thực hiện cho thấy một ước tính hoàn toàn giống như khi chỉ có số liệu thống kê cột đơn:

Gói thống kê nhiều cột

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.