2013-01-08 28 views
14

Tôi có truy vấn sql bên dưới đang chạy rất chậm. Tôi đã xem xét kế hoạch thực hiện và tuyên bố rằng một loại trên Files.OrderId là hoạt động chi phí cao nhất (53%). Tại sao điều này sẽ xảy ra nếu tôi không đặt hàng bởi OrderId ở đâu? Đặt cược của tôi tốt nhất để tạo một chỉ mục trên File.OrderId?Tại sao có một loại hiển thị trong kế hoạch thực hiện của tôi?

Execution plan nếu có ai quan tâm.

with custOrders as 
(
    SELECT c.firstName + ' ' + c.lastname as Customer, c.PartnerId , c.CustomerId,o.OrderId,o.CreateDate, c.IsPrimary 
    FROM Customers c 
    LEFT JOIN CustomerRelationships as cr 
     ON c.CustomerId = cr.PrimaryCustomerId 
    INNER JOIN Orders as o 
     ON c.customerid = o.customerid 
      OR (cr.secondarycustomerid IS NOT NULL AND o.customerid = cr.secondarycustomerid) 
    where c.createdate >= @FromDate + ' 00:00' 
     AND c.createdate <= @ToDate + ' 23:59' 
), 
temp as 
(
SELECT Row_number() 
     OVER ( 
      ORDER BY c.createdate DESC)     AS 'row_number', 
     c.customerid as customerId, 
     c.partnerid as partnerId, 
     c.Customer, 
     c.orderid as OrderId, 
     c.createdate as CreateDate, 
     Count(f.orderid)         AS FileCount, 
     dbo.Getparentcustomerid(c.isprimary, c.customerid) AS ParentCustomerId, 
     au.firstname + ' ' + au.lastname     AS Admin, 
     '' as blank, 
     0 as zero 
FROM custOrders c 
     INNER JOIN files f 
       ON c.orderid = f.orderid 
     INNER JOIN admincustomers ac 
       ON c.customerid = ac.customerid 
     INNER JOIN adminusers au 
       ON ac.adminuserid = au.id 
     INNER JOIN filestatuses s 
       ON f.statusid = s.statusid 
WHERE ac.adminuserid IS NOT NULL 
     AND f.statusid NOT IN (5, 6) 
GROUP BY c.customerid, 
      c.partnerid, 
      c.Customer, 
      c.isprimary, 
      c.orderid, 
      c.createdate, 
      au.firstname, 
      au.lastname 
) 
+0

* Lỗi khi xác thực nguồn XML * – Kermit

+0

Vâng tôi đã thấy điều đó. Liệu nó thực sự làm cho một sự khác biệt? Bạn vẫn có thể thấy XML ... –

+0

Không phải là 'OVER' có nghĩa là sắp xếp? – Kermit

Trả lời

11

Máy chủ SQL có ba thuật toán để chọn khi cần tham gia hai bảng. Nested-Loops-Join, Hash-Join và Sort-Merge-Join. Cái nào nó chọn dựa trên ước tính chi phí. Trong trường hợp này nó đã tìm ra, dựa trên thông tin mà nó đã có sẵn một Sort-Merge-Join là lựa chọn đúng đắn.

Trong kế hoạch thực thi SQL Server, Sort-Merge được chia thành hai toán tử, Sort và Merge-Join, vì thao tác sắp xếp có thể không cần thiết, ví dụ nếu dữ liệu được sắp xếp.

Để biết thông tin mor về tham gia kiểm tra hàng loạt tham gia của tôi ở đây: http://sqlity.net/en/1146/a-join-a-day-introduction/ Các bài viết về Sort-Merg-Tham gia là ở đây: http://sqlity.net/en/1480/a-join-a-day-the-sort-merge-join/


Để thực hiện truy vấn của bạn nhanh hơn, lần đầu tiên tôi sẽ nhìn vào chỉ số . Bạn có một loạt các quét chỉ mục nhóm trong truy vấn. Nếu bạn có thể thay thế một vài người trong số họ bằng cách tìm kiếm, bạn sẽ có nhiều khả năng tốt hơn. Ngoài ra, hãy kiểm tra xem các ước tính SQL Server có khớp với số hàng thực tế trong kế hoạch thực thi thực tế hay không. Nếu chúng ở xa, SQL Server thường có những lựa chọn không tốt. Vì vậy, việc cung cấp thống kê tốt hơn có thể giúp bạn truy vấn hiệu suất.

+0

+1 cho số lượng hàng thực tế và số liệu thống kê –

1

Tôi nghĩ rằng các loại đang xảy ra cho gia này:

FROM custOrders c 
     INNER JOIN files f 
       ON c.orderid = f.orderid 

tôi sẽ tạo ra một chỉ số trên các tập tin trong đó bao gồm các cột OrderID và statusid kể từ khi truy vấn cũng sử dụng cột statusid.

Bạn cũng có thể muốn xem xét các thay đổi sau:

  1. Bạn không cần phải "ac.adminuserid IS NOT NULL" như thế này được bao phủ bởi liên kết nội giữa adminusers và admincustomers
  2. Thay đổi kiểm tra "f.statusid NOT IN (5, 6)" với điều kiện dương (ví dụ In) là điều kiện tiêu cực sẽ tốn kém hơn để xử lý.
+0

[tệp] đã có chỉ mục bao gồm –

+0

Vâng, nó đã làm một chỉ mục không được nhóm tìm kiếm trên 'Tệp'. Có cách nào để tiếp tục giảm số lượng bản ghi đến từ 'Tệp' không? –

+0

Một chỉ mục không nhóm được tìm kiếm là tốt từ một quan điểm hiệu suất. Sự thay đổi khác để giảm số lượng bản ghi là loại bỏ kiểm tra NOT IN chống lại trạng thái như tôi đã đề nghị ở trên. –

2

Máy chủ SQL đang thực hiện sắp xếp để cho phép kết hợp hợp nhất giữa tập dữ liệu ở bên phải toán tử sắp xếp đó và các bản ghi trong bảng Orders. Hợp nhất tham gia chính nó là một cách rất hiệu quả để tham gia tất cả các bản ghi trong một tập dữ liệu, nhưng nó đòi hỏi rằng mỗi tập dữ liệu để được tham gia được sắp xếp theo các khóa tham gia và theo cùng thứ tự.

Vì khóa PK_Orders đã được đặt hàng trước OrderID, SQL Server quyết định tận dụng điều đó bằng cách sắp xếp đầu kia của kết nối (các công cụ khác ở bên phải sắp xếp) để hai tập hợp dữ liệu có thể được hợp nhất với nhau tại thời điểm đó trong kế hoạch. Cách thay thế phổ biến để kết hợp kết hợp là một phép nối băm, nhưng điều đó sẽ không giúp bạn bởi vì thay vào đó bạn sẽ có toán tử băm nối đắt tiền thay vì sắp xếp và hợp nhất. Trình tối ưu hóa truy vấn đã xác định sắp xếp và hợp nhất để có hiệu quả hơn trong trường hợp này.

Nguyên nhân gốc rễ của bước tốn kém trong kế hoạch là cần phải kết hợp tất cả các bản ghi từ bảng đơn đặt hàng vào tập dữ liệu. Có cách nào để hạn chế các hồ sơ đến từ bảng files không? Chỉ số trên files.statusid có thể hữu ích nếu các bản ghi không ở mức 5,6 nhỏ hơn 10% tổng kích thước bảng.

QO cho rằng hầu hết các bản ghi sẽ được lọc ra ở cuối. Cố gắng đẩy càng nhiều điều kiện lọc trở lại nguồn bản ghi để ít hồ sơ phải được xử lý ở giữa kế hoạch.

EDIT: Tôi quên đề cập đến, rất hữu ích khi có kế hoạch thực hiện mà chúng tôi có thể xem xét. Có cách nào chúng ta có thể nhận được kết quả kế hoạch thực thi thực tế để xem số lượng hồ sơ thực sự trải qua các toán tử đó không? Đôi khi số lượng hồ sơ ước tính có thể giảm một chút.

EDIT: Nhìn sâu hơn vào thứ 2 đến lĩnh vực thuộc tính lọc cuối cùng nhà điều hành, tóm tắt:

c.CustomerId=o.CustomerId 
OR o.CustomerId=cr.SecondaryCustomerId AND cr.SecondaryCustomerId IS NOT NULL 

Hình như SQL Server đang sản xuất một chéo tham gia giữa tất cả hồ sơ phù hợp có thể có giữa OrdersCustomers lên đến này điểm trong truy vấn (kế hoạch ở bên phải của nhà điều hành bộ lọc thứ 2 đến cuối cùng) và sau đó xem từng bản ghi với điều kiện đó để xem liệu nó có thực sự khớp hay không. Chú ý rằng đường dây đi vào bộ lọc thực sự là chất béo và dòng ra là thực sự mỏng? Đó là vì số lượng hàng ước tính đi từ 21k đến 4 sau toán tử đó. Hãy quên đi những gì tôi đã nói trước đó, đây có lẽ là vấn đề chính trong kế hoạch. Ngay cả khi có các chỉ mục trên các cột này, SQL Server không thể sử dụng chúng vì điều kiện kết nối quá phức tạp. Nó gây ra kế hoạch hợp nhất tất cả các bản ghi với nhau thay vì chỉ tìm kiếm những bản ghi bạn cần bởi vì nó không thể sử dụng vị từ nối đầy đủ ngay lập tức.

Suy nghĩ đầu tiên của tôi là thuật lại CTE custOrders làm công đoàn của hai bộ dữ liệu: một sử dụng CustomerId và một sử dụng SecondaryCustomerId để tham gia. Điều này sẽ lặp lại công việc của phần còn lại của CTE nhưng nếu nó cho phép sử dụng đúng các chỉ số, nó có thể là một chiến thắng lớn.

+0

Ok, tôi đã cập nhật với gói thực tế –

+0

Vẫn trông giống như gói ước tính ban đầu. Bạn có chỉnh sửa câu hỏi hoặc thay đổi tài liệu trên XML Playground không? –

0

Tôi biết câu hỏi này là khá cũ, tuy nhiên tôi đã có cùng một vấn đề này và nhận ra có một lý do hoàn toàn khác khiến các bảng của tôi đột nhiên bị chậm lại. Các triệu chứng đều giống nhau, chậm để cập nhật các lượt xem trước đây nhanh như chớp. "Sắp xếp" với chi phí là 40%. Giải pháp này có thể hữu ích cho ai đó, và nó rất đơn giản. Khi tham gia các bảng, đảm bảo bạn đang tham gia trên cơ sở "thích". Tôi đã tham gia hai bảng trên ID. Tuy nhiên trong một bảng ID của tôi đã được thiết lập như là một int và trong khác như nvarchar. Tôi đã sửa lỗi này để có cả hai được định nghĩa là cùng loại và chế độ xem quay lại tốc độ cực nhanh.

hy vọng điều này sẽ giúp người khác tránh chi tiêu một tuần cố gắng tìm ra điều gì sai với SQL, khi đó thực sự là thời điểm PEBKAC.

(Sự cố tồn tại giữa bàn phím và ghế)

Các vấn đề liên quan