Truy vấn T-SQL sử dụng gói hoàn toàn khác nhau tùy thuộc vào số lượng hàng tôi đang cập nhật


20

Tôi có một câu lệnh CẬP NHẬT SQL với mệnh đề "TOP (X)" và hàng tôi đang cập nhật các giá trị trong có khoảng 4 tỷ hàng. Khi tôi sử dụng "TOP (10)", tôi nhận được một kế hoạch thực hiện gần như ngay lập tức, nhưng khi tôi sử dụng "TOP (50)" hoặc lớn hơn, truy vấn không bao giờ (ít nhất là trong khi tôi đang chờ) kết thúc và nó sử dụng một kế hoạch thực hiện hoàn toàn khác. Truy vấn nhỏ hơn sử dụng một kế hoạch rất đơn giản với một cặp tìm kiếm chỉ mục và nối vòng lặp lồng nhau, trong đó cùng một truy vấn (với một số hàng khác nhau trong mệnh đề TOP của câu lệnh UPDATE) sử dụng một kế hoạch bao gồm hai tìm kiếm chỉ mục khác nhau , một bộ đệm bảng, song song và một loạt các phức tạp khác.

Tôi đã sử dụng "TÙY CHỌN (SỬ DỤNG KẾ HOẠCH ...)" để buộc nó sử dụng kế hoạch thực hiện được tạo bởi truy vấn nhỏ hơn - khi tôi thực hiện việc này, tôi có thể cập nhật lên tới 100.000 hàng trong vài giây. Tôi biết kế hoạch truy vấn là tốt, nhưng SQL Server sẽ chỉ chọn kế hoạch đó khi chỉ có một số lượng nhỏ hàng - bất kỳ số lượng hàng lớn nào trong bản cập nhật của tôi sẽ dẫn đến kế hoạch tối ưu phụ.

Tôi nghĩ rằng sự song song có thể là đáng trách, vì vậy tôi đã đặt MAXDOP 1ra truy vấn, nhưng không có kết quả - bước đó không còn nữa, nhưng sự lựa chọn / hiệu suất kém thì không. Tôi cũng sp_updatestatsvừa mới chạy sáng nay để đảm bảo đó không phải là nguyên nhân.

Tôi đã đính kèm hai kế hoạch thực hiện - kế hoạch ngắn hơn cũng nhanh hơn. Ngoài ra, đây là truy vấn được đề cập (đáng lưu ý rằng CHỌN tôi đã đưa vào dường như nhanh chóng trong các trường hợp cả số lượng hàng nhỏ và lớn):

    update top (10000) FactSubscriberUsage3
               set AccountID = sma.CustomerID
    --select top 50 f.AccountID, sma.CustomerID
      from FactSubscriberUsage3 f
      join dimTime t
        on f.TimeID = t.TimeID
      join #mac sma
        on f.macid = sma.macid
       and t.TimeValue between sma.StartDate and sma.enddate 
     where f.AccountID = 0 --There's a filtered index on the table for this

Đây là kế hoạch nhanh : Kế hoạch thực hiện nhanh chóng

Và đây là cái chậm hơn : Kế hoạch thực hiện chậm

Có bất cứ điều gì rõ ràng trong cách tôi thiết lập truy vấn của mình hoặc trong kế hoạch thực hiện với điều kiện sẽ tự cho mình lựa chọn xấu mà công cụ truy vấn đang thực hiện không? Nếu cần, tôi cũng có thể bao gồm các định nghĩa bảng liên quan và các chỉ mục được xác định trên chúng.

Đối với những người yêu cầu phiên bản chỉ thống kê của các đối tượng cơ sở dữ liệu: Tôi thậm chí không nhận ra bạn có thể làm điều đó, nhưng nó hoàn toàn có ý nghĩa! Tôi đã cố gắng tạo các tập lệnh cho cơ sở dữ liệu chỉ thống kê để người khác có thể tự kiểm tra các kế hoạch thực hiện, nhưng tôi có thể tạo các số liệu thống kê / biểu đồ trên chỉ mục được lọc của mình (có vẻ như lỗi cú pháp trong tập lệnh) hết may mắn đấy Tôi đã cố gắng loại bỏ bộ lọc và các kế hoạch truy vấn đã gần, nhưng không hoàn toàn giống nhau và tôi không muốn gửi bất kỳ ai theo đuổi ngỗng.

Cập nhật và một số kế hoạch thực hiện đầy đủ hơn: Trước hết, Plan Explorer của SQL Sentry là một công cụ đáng kinh ngạc. Tôi thậm chí không biết nó tồn tại cho đến khi xem các câu hỏi khác của kế hoạch truy vấn trên trang web này và có khá nhiều điều để nói về cách các truy vấn của tôi đang thực hiện. Mặc dù tôi không chắc cách giải quyết vấn đề, họ đã nói rõ vấn đề là gì.

Dưới đây là tóm tắt cho 10, 100 và 1000 hàng - bạn có thể thấy rằng truy vấn 1000 hàng là cách, không phù hợp với các hàng khác: Tóm tắt báo cáo

Bạn có thể thấy rằng truy vấn thứ ba có số lần đọc vô lý, vì vậy rõ ràng nó đang làm một cái gì đó hoàn toàn khác. Đây là kế hoạch thực hiện ước tính, với số lượng hàng. Kế hoạch thực hiện ước tính 1000 hàng: Kế hoạch thực hiện ước tính 1000 hàng

Và đây là kết quả thực tế của kế hoạch thực hiện (nhân tiện, "không bao giờ kết thúc", hóa ra tôi có nghĩa là "kết thúc trong một giờ"). Kế hoạch thực hiện 1000 hàng Kế hoạch thực hiện 1000 hàng

Điều đầu tiên tôi nhận thấy là, thay vì kéo 60K hàng từ bảng dimTime như dự kiến, nó thực sự kéo 1,6 tỷ, với B . Nhìn vào truy vấn của tôi, tôi không chắc chắn làm thế nào nó lấy lại được nhiều hàng từ bảng dimTime. Toán tử BETweEN tôi đang sử dụng chỉ đảm bảo rằng tôi lấy bản ghi chính xác từ #mac dựa trên bản ghi thời gian trong bảng Fact. Tuy nhiên, khi tôi thêm một dòng vào mệnh đề WHERE nơi tôi lọc t.TimeValue (hoặc t.TimeID) thành một giá trị duy nhất, tôi có thể cập nhật thành công 100.000 hàng trong vài giây. Do đó, và như đã nói rõ trong các kế hoạch thực hiện mà tôi đưa vào, rõ ràng bảng thời gian của tôi là vấn đề, nhưng tôi không chắc mình đã thay đổi tiêu chí tham gia như thế nào để giải quyết vấn đề này và duy trì độ chính xác . Có suy nghĩ gì không?

Để tham khảo, ở đây kế hoạch (có số lượng hàng) cho bản cập nhật 100 hàng. Bạn có thể thấy rằng nó đạt cùng một chỉ mục và vẫn có hàng tấn hàng, nhưng không nơi nào có cùng mức độ của một vấn đề. Thực hiện 100 hàng với số lượng hàng : nhập mô tả hình ảnh ở đây


Đó là số liệu thống kê của GOTTA. Bạn đã chạy một cái sp_updatestatisticstrên bàn?
JNK

@JNK: Ban đầu tôi cũng nghĩ vậy, nhưng đã chạy sp_updatestats mà không thay đổi. Tôi chỉ chạy lại nó và không quan tâm cập nhật số liệu thống kê về bất kỳ chỉ mục nào liên quan đến truy vấn. Cảm ơn mặc dù!
SqlRyan

Kế hoạch thứ hai là một kế hoạch cập nhật rộng (trên mỗi chỉ mục) thay vì kế hoạch hẹp (mỗi hàng) giải thích một số phức tạp có thể nhìn thấy thêm. Nhưng thực sự khác biệt duy nhất là tham gia trật tự from #mac sma join f on f.macid = sma.macid join dimTime t on f.TimeID = t.TimeID and t.TimeValue between sma.StartDate and sma.enddatevsfrom #mac join t on t.TimeValue between sma.StartDate and sma.enddate join f on f.TimeID = t.TimeID and f.macid = sma.macid
Martin Smith

Có gì đó không đúng ở đây. Ngay cả kế hoạch truy vấn đắt tiền cũng sẽ tạo ra các hàng tăng dần. A TOP 50vẫn nên thực hiện nhanh chóng. Bạn có thể tải lên các kế hoạch XML? Tôi cần nhìn vào số lượng hàng. Bạn có thể chạy TOP 50với maxdop 1 và dưới dạng chọn, không phải là bản cập nhật và đăng kế hoạch không? (Cố gắng đơn giản hóa / chia đôi không gian tìm kiếm).
usr

@usr tham gia t.TimeValue between sma.StartDate and sma.enddatecó thể sẽ tạo ra nhiều hàng vô dụng hơn mà sau đó được lọc ra trong liên kết với FactSubscacker và do đó không kết thúc cuối cùng.
Martin Smith

Câu trả lời:


3

Chỉ mục trên dimTime đang thay đổi. Kế hoạch nhanh hơn là sử dụng chỉ số _dta. Trước hết, hãy đảm bảo rằng không được đánh dấu là một chỉ số giả định trong sys.indexes.

Nghĩ rằng bạn có thể bỏ qua một số tham số hóa bằng cách sử dụng bảng #mac để lọc thay vì chỉ cung cấp ngày bắt đầu / ngày kết thúc như thế này WHERE t.TimeValue giữa @StartDate và @enddate. Loại bỏ bảng tạm thời đó.


Chỉ mục tiền tố dta trông giống như được tạo bằng cách làm theo khuyến nghị DTA mà không tùy chỉnh tên. Các chỉ mục giả thuyết không thể xuất hiện trong các kế hoạch thực hiện thực tế (và sẽ không được ước tính nếu không có một số lệnh không có giấy tờ). Không chắc làm thế nào đề nghị thứ hai của bạn sẽ làm việc. t.TimeValue between sma.StartDate and sma.enddateđược tương quan để có thể thay đổi cho mỗi hàng trong #tempbảng. OP sẽ thay thế nó bằng gì?
Martin Smith

Đủ công bằng, tôi đã không chú ý đầy đủ đến bảng tạm thời.
william_a_dba

1
Tuy nhiên, các chỉ số giả thuyết thực sự có thể làm hỏng một kế hoạch thực hiện. Nếu nó là giả thuyết, nó nên được loại bỏ và tái tạo. blog.technet.com/b/anurag_sharma/archive/2008/04/15/ từ
william_a_dba

Các chỉ số giả thuyết còn sót lại khi DTA không kết thúc / đóng băng trước khi hoàn thành. Bạn phải dọn dẹp chúng bằng tay nếu có bất kỳ trục trặc nào với DTA.
william_a_dba

1
@william_a_dba - Ah tôi hiểu ý của bạn lúc này (sau khi đọc liên kết của bạn). Truy vấn không bao giờ kết thúc có thể là nó liên tục biên dịch lại. Hấp dẫn!
Martin Smith

1

Không có thêm thông tin về số lượng hàng trong kế hoạch, khuyến nghị sơ bộ của tôi là sắp xếp thứ tự tham gia chính xác trong truy vấn và buộc sử dụng nó OPTION (FORCE ORDER). Thực thi thứ tự tham gia của kế hoạch đầu tiên.

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.