So sánh hai truy vấn trong SQL Server 2012


14

Tôi đang so sánh hai truy vấn trong SQL Server 2012. Mục tiêu là sử dụng tất cả các thông tin thích hợp có sẵn từ trình tối ưu hóa truy vấn khi chọn truy vấn tốt nhất. Cả hai truy vấn đều cho kết quả như nhau; trật tự tối đa cho tất cả khách hàng.

Việc xóa nhóm bộ đệm đã được thực hiện trước khi thực hiện từng truy vấn với FREEPROCCACHE và DROPCLEANBUFFERS

Sử dụng thông tin được cung cấp dưới đây, truy vấn nào là sự lựa chọn tốt hơn?

-- Query 1 - return the maximum order id for a customer
SELECT orderid, custid
FROM Sales.Orders AS O1
WHERE orderid = (SELECT MAX(O2.orderid)
                 FROM Sales.Orders AS O2
                 WHERE O2.custid = O1.custid);


-- Query 2 - return the maximum order id for a customer
SELECT MAX(orderid), custid
FROM Sales.Orders AS O1
group by custid
order by custid

THỐNG KÊ THỜI GIAN

Truy vấn 1 THỐNG KÊ THỜI GIAN: Thời gian CPU = 0ms, thời gian trôi qua = 24 ms

Truy vấn 2 THỐNG KÊ THỜI GIAN: Thời gian CPU = 0 ms, thời gian trôi qua = 23 ms

THỐNG KÊ IO

Truy vấn 1 THỐNG KÊ IO: Bảng 'Đơn hàng'. Quét số 1, đọc logic 5, đọc vật lý 2, đọc trước đọc 0, đọc logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Truy vấn 2 THỐNG KÊ IO: Bảng 'Đơn hàng'. Quét số 1, đọc logic 4, đọc vật lý 1, đọc trước 8, đọc logic logic 0, đọc vật lý lob 0, đọc trước đọc 0, đọc trước 0.

Kế hoạch thực hiện

nhập mô tả hình ảnh ở đây

CHỌN thuộc tính Truy vấn 1

nhập mô tả hình ảnh ở đây

CHỌN thuộc tính Truy vấn 2

nhập mô tả hình ảnh ở đây

Kết luận:

Truy vấn 1

  1. Chi phí hàng loạt 48%
  2. Logic đọc 5
  3. Đọc vật lý 2
  4. Đọc trước Đọc: 0
  5. Thời gian CPU: 0ms
  6. Thời gian trôi qua 24ms
  7. Chi phí phụ dự kiến: 0,0050276
  8. Biên dịchCPU: 2
  9. CompileMemory: 384
  10. Thời gian biên dịch: 2

Truy vấn 2

  1. Chi phí hàng loạt 52%
  2. Logic đọc 4
  3. Vật lý đọc 1
  4. Đọc trước Đọc: 8
  5. Thời gian CPU 0
  6. Thời gian trôi qua 23ms
  7. Chi phí phụ dự kiến: 0,0054782
  8. Biên dịchCPU: 0
  9. CompileMemory: 192
  10. Thời gian biên dịch: 0

Cá nhân, mặc dù Truy vấn 2 có chi phí lô cao hơn theo kế hoạch đồ họa, tôi nghĩ rằng Truy vấn 1. hiệu quả hơn bởi Truy vấn 2 này yêu cầu đọc ít logic hơn, thời gian trôi qua thấp hơn một chút, các giá trị compilecpu, compilememory và compllime thấp hơn. đọc trước đọc là 8 cho truy vấn 2 và 0 cho truy vấn 1.

Cập nhật 12:03

Định nghĩa chỉ mục cụm

ALTER TABLE [Sales].[Orders] ADD  CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
    [orderid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Chỉ mục không phân cụm idx_nc_custid

CREATE NONCLUSTERED INDEX [idx_nc_custid] ON [Sales].[Orders]
(
    [custid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO

Bình luận không dành cho thảo luận mở rộng; cuộc trò chuyện này đã được chuyển sang trò chuyện .
Paul White 9

Câu trả lời:


10

Tôi thích cách tiếp cận của bạn để xem xét cẩn thận để điều chỉnh truy vấn và xem xét các tùy chọn và kế hoạch. Tôi muốn nhiều nhà phát triển đã làm điều này. Một lưu ý sẽ là - luôn luôn kiểm tra với rất nhiều hàng, nhìn vào các lần đọc logic, đây là một bảng nhỏ. Hãy thử và tạo một tải mẫu và chạy lại truy vấn. Một vấn đề nhỏ - trong truy vấn hàng đầu của bạn, bạn không yêu cầu một đơn đặt hàng, trong truy vấn dưới cùng của bạn, bạn đang có. Bạn nên so sánh và đối chiếu chúng với từng thứ tự.

Tôi vừa nhanh chóng tạo ra một bảng SalesOrder với 200.000 đơn đặt hàng trong đó - vẫn không lớn bằng bất kỳ sự tưởng tượng nào. Và chạy các truy vấn với ORDER BY trong mỗi. Tôi cũng chơi với chỉ số một chút.

Không có chỉ mục được phân cụm trên OrderID, chỉ là một chỉ mục không được phân cụm trên CustID Truy vấn thứ hai vượt trội hơn. Đặc biệt với thứ tự bao gồm trong mỗi. Có gấp đôi số lần đọc trên truy vấn đầu tiên so với truy vấn thứ hai và tỷ lệ phần trăm chi phí là 67% / 33% giữa các truy vấn.

Với một chỉ mục được nhóm trên OrderID và một chỉ mục không được phân cụm chỉ trên CustID Họ đã thực hiện ở một tốc độ tương tự và cùng số lần đọc chính xác.

Vì vậy, tôi sẽ đề nghị bạn tăng số lượng hàng và thực hiện thêm một số thử nghiệm. Nhưng phân tích cuối cùng của tôi về các truy vấn của bạn -

Bạn có thể thấy chúng hoạt động tương tự như bạn nhận ra khi bạn tăng các hàng, vì vậy hãy ghi nhớ điều đó và kiểm tra theo cách đó.

Nếu tất cả những gì bạn muốn trả về là OrderID tối đa cho mỗi Khách hàng và bạn muốn xác định rằng OrderID là OrderID lớn nhất thì truy vấn thứ hai trong số này là cách tốt nhất để đi khỏi suy nghĩ của tôi - đó là một chút đơn giản hơn và mặc dù đắt hơn một chút dựa trên chi phí cây con, đó là một tuyên bố giải mã nhanh hơn và dễ dàng hơn. Nếu bạn có ý định thêm các cột khác vào tập kết quả của bạn một ngày nào đó? Sau đó, truy vấn đầu tiên cho phép bạn làm điều đó.

Cập nhật: Một trong những ý kiến ​​của bạn dưới câu hỏi của bạn là:

Xin lưu ý rằng việc tìm kiếm truy vấn tốt nhất trong câu hỏi này là một phương tiện để tinh chỉnh các kỹ thuật được sử dụng để so sánh chúng.

Nhưng tốt nhất để thực hiện điều đó - kiểm tra với nhiều dữ liệu hơn - luôn đảm bảo bạn có dữ liệu phù hợp với sản xuất và sản xuất dự kiến ​​trong tương lai. Các gói truy vấn bắt đầu tìm kiếm dữ liệu khi bạn cung cấp nhiều hàng hơn cho các bảng và thử và giữ phân phối những gì bạn mong đợi trong sản xuất. Và chú ý đến những thứ như bao gồm cả Order By hay không, ở đây tôi không nghĩ rằng nó tạo ra một chút khác biệt khủng khiếp cuối cùng, nhưng vẫn đáng để đào sâu vào.

Cách tiếp cận của bạn để so sánh mức độ chi tiết và dữ liệu này là một cách tốt. Chi phí phụ là chủ yếu tùy ý và vô nghĩa, nhưng vẫn có giá trị ít nhất là xem xét để so sánh giữa các chỉnh sửa / thay đổi hoặc thậm chí giữa các truy vấn. Nhìn vào số liệu thống kê thời gian và IO khá quan trọng, cũng như xem xét kế hoạch cho bất cứ điều gì cảm thấy không phù hợp với kích thước của dữ liệu bạn đang làm việc và những gì bạn đang cố gắng thực hiện.


Xin chào một lần nữa, cảm ơn bạn đã cho điểm của bạn về việc sử dụng khối lượng dữ liệu lớn hơn. Đây không phải là lần đầu tiên ai đó đưa nó lên. Lần cuối cùng mặc dù đã xem xét phân mảnh có thể từ các phân chia trang. Trong mẫu 200.000 hàng của bạn, bạn đã kiểm tra phân mảnh chưa?
Craig Efrein

Vâng, trong ví dụ hàng 200k nhanh chóng nhỏ của tôi, tôi đã không tập trung vào phân mảnh, không. Nhưng cách tôi đã làm nó sẽ không có. Tôi đã tạo bảng, điền vào bảng và sau đó tạo các chỉ mục, Vì vậy, chúng là các chỉ mục được tạo mới. Và điều đó sẽ không thay đổi cách tiếp cận xem xét các kế hoạch truy vấn dường như là câu hỏi chính. Khối lượng dữ liệu lớn - thực sự lớn - khi xem xét các kế hoạch truy vấn một cách chính xác. Tôi thường thấy các trường hợp trông tuyệt vời ở dev (với 1-10 hàng) và thật kinh khủng khi sử dụng dữ liệu thực. Nhưng cách tiếp cận của bạn là tốt và hy vọng thông tin này và cuộc trò chuyện trong các bình luận sẽ giúp ích
Mike Walsh

Vì chúng tôi đang phân nhóm theo quyền giám hộ, làm thế nào bạn tạo ra các giá trị lưu ký đủ ngẫu nhiên? Một điều tôi nhớ từ bài đọc của mình, là tầm quan trọng của các giá trị riêng biệt. Nếu lưu ký chỉ có một số lượng nhỏ khách hàng riêng biệt, thì chi phí cho tổng hợp luồng sẽ không thực tế.
Craig Efrein

Tôi chỉ sử dụng chức năng RAND để tạo 100 khách hàng và chỉ định ngẫu nhiên một khách hàng cho mỗi orderID .. Tôi đang thực hiện kiểm tra nhanh. :)
Mike Walsh

Cảm ơn Mike vì tất cả sự giúp đỡ của bạn. Một câu hỏi cuối cùng mặc dù. Từ màn hình thuộc tính CHỌN từ Kế hoạch thực hiện năm 2012 mà tôi đã cung cấp trong câu hỏi của mình, bạn chú ý đến những giá trị nào?
Craig Efrein
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.