2009-06-05 29 views
36

Delete s trên máy chủ sql đôi khi chậm và tôi thường cần tối ưu hóa chúng để giảm bớt thời gian cần thiết. Tôi đang tìm kiếm một số mẹo nhỏ về cách thực hiện điều đó và tôi đã tìm thấy các đề xuất đa dạng. Tôi muốn biết kỹ thuật viên yêu thích và hiệu quả nhất của bạn để chế ngự con thú xóa, và cách thức và lý do chúng hoạt động.Tối ưu hóa Xóa trên Máy chủ SQL

đến nay:

  • hãy chắc chắn phím nước ngoài có chỉ số

  • hãy chắc chắn các điều kiện nơi được lập chỉ mục

  • sử dụng WITH ROWLOCK

  • phá hủy chỉ số chưa sử dụng, xóa , xây dựng lại các chỉ mục

bây giờ, đến lượt bạn.

+0

Câu hỏi cho người sử dụng điện: câu hỏi này không có một câu trả lời duy nhất, là một loại cơ sở tri thức hơn là một câu hỏi trả lời đơn giản. Có thể nào nó có thể trở thành một wiki cộng đồng? (nếu tôi hiểu rõ về một điều gì là dành cho) – pomarc

+0

Tôi muốn xem nó như là một bản tóm tắt đang diễn ra. Bài đăng này rất hữu ích với tôi nhưng đã mất nhiều giờ để đọc qua các đề xuất. Tôi đã gửi một bản chỉnh sửa với bản tóm tắt mới bị từ chối, chờ xem thử thứ hai có đi qua không :) – xero

+0

@xero Tôi đã khôi phục bản chỉnh sửa, bạn có thể gắn cờ quản trị viên để chú ý (sử dụng khác) sau khi đọc [Nên cộng đồng wiki cảnh sát bị đóng cửa?] (http://meta.stackexchange.com/questions/392/should-the-community-wiki-police-be-shut-down) [Chúng ta có thể làm gì để làm cho Wiki Cộng đồng trở nên tốt hơn? ] (http://meta.stackexchange.com/questions/67039/what-can-we-do-to-make-community-wiki-better) và http://meta.stackoverflow.com/a/266921 – bummi

Trả lời

21

Bài viết sau, Đặt hàng nhanh Xóa thao tác có thể bạn quan tâm.

Performing fast SQL Server delete operations

Các giải pháp tập trung vào việc sử dụng một cái nhìn để đơn giản hóa các kế hoạch thực hiện sản xuất cho một đồng loạt xóa hoạt động. Điều này đạt được bằng cách tham khảo bảng đã cho một lần, thay vì hai lần lần lượt làm giảm số lượng I/O cần thiết.

+1

Giấy gốc không còn có sẵn tại liên kết được chỉ định, nhưng liên kết có sẵn ở dạng lưu trữ tại đây: https://web.archive.org/web/20100212155407/http://blogs.msdn.com/ sqlcat/archive/2009/05/21/fast-ordered-delete.aspx (mũ tip cho William Isted qua https://www.codelibrary.me/2012/08/01/perform-fast-mssql-delete-operations/) – Dragonsdoom

12

tôi có kinh nghiệm nhiều hơn nữa với Oracle, nhưng rất có khả năng tương tự áp dụng cho SQL Server cũng như:

  • khi xóa một số lượng lớn của các hàng, vấn đề một khóa bảng, vì vậy cơ sở dữ liệu không có để thực hiện rất nhiều khóa hàng
  • nếu bảng bạn xóa từ được tham chiếu bởi các bảng khác, hãy đảm bảo rằng các bảng khác có chỉ mục trên cột khóa ngoài (nếu không cơ sở dữ liệu sẽ quét toàn bộ cho từng bảng đã xóa hàng trên bảng khác để đảm bảo xóa hàng không vi phạm ràng buộc khóa ngoại)
+2

bảng khóa sẽ ngăn chặn chèn và cập nhật trên bàn, cần phải đảm bảo xóa nhanh trước khi các giao dịch khác bắt đầu định thời gian. – dsum

+0

dsum: true, nhưng xóa một số lượng lớn các bản ghi là điều thường xảy ra trong cửa sổ bảo trì mà không có hoạt động khác (ví dụ: vào ban đêm). –

4

(nếu các chỉ số là "không sử dụng", tại sao họ có ở tất cả?)

Một lựa chọn Tôi đã sử dụng trong quá khứ là để làm công việc theo lô. Cách thô sẽ là sử dụng SET ROWCOUNT 20000 (hoặc bất kỳ) và vòng lặp (có lẽ với một WAITFOR DELAY) cho đến khi bạn thoát khỏi tất cả (@@ ROWCOUNT = 0).

Điều này có thể giúp giảm tác động trên các hệ thống khác.

+0

"không sử dụng" trong xóa – pomarc

+0

Nhưng có nhiều điều khác thường xảy ra hơn là chỉ xóa ... Tôi đoán nó có thể giúp, nhưng bạn phải kiểm tra xem nó không (tổng thể) làm cho hệ thống tồi tệ hơn .. –

+0

Không xóa chỉ mục chỉ vì chúng không được sử dụng trong xóa! Những người khác đang sử dụng cơ sở dữ liệu cho những thứ khác! – HLGEM

5

Thành thật mà nói, xóa hàng triệu hàng khỏi một bảng có kích thước chỉ nặng như chèn hoặc cập nhật hàng triệu hàng. Đó là kích thước của các rowset đó là vấn đề, và không có nhiều bạn có thể làm về điều đó.

gợi ý của tôi:

  • Hãy chắc chắn rằng bảng có một khóa chính và chỉ số nhóm (điều này là rất quan trọng cho tất cả các hoạt động).
  • Đảm bảo rằng chỉ mục được nhóm sao cho việc tổ chức lại trang tối thiểu sẽ xảy ra nếu một khối lớn các hàng bị xóa.
  • Đảm bảo rằng tiêu chí lựa chọn của bạn là SARGable.
  • Đảm bảo rằng tất cả các ràng buộc khóa ngoại của bạn hiện được tin cậy.
+8

SARGable: Trong cơ sở dữ liệu quan hệ, một điều kiện (hoặc vị ngữ) trong truy vấn được cho là có thể sargable nếu công cụ DBMS có thể tận dụng một chỉ số để tăng tốc độ thực hiện truy vấn (sử dụng chỉ mục tìm kiếm, không bao gồm các chỉ mục). Thuật ngữ này bắt nguồn từ sự co lại của ARGR tìm kiếm. (Wikipedia) – pomarc

2

tôi sẽ thêm một số khác như sau:

Hãy chắc chắn rằng giao dịch mức cô lập và cơ sở dữ liệu của bạn tùy chọn được thiết lập một cách thích hợp. Nếu máy chủ SQL của bạn được đặt không sử dụng phiên bản hàng hoặc bạn đang sử dụng mức cách ly trên các truy vấn khác, nơi bạn sẽ chờ các hàng bị xóa, bạn có thể tự thiết lập hiệu suất rất kém trong khi hoạt động đang diễn ra .

2

Trên các bảng rất lớn nơi bạn có một bộ tiêu chí rất cụ thể để xóa, bạn cũng có thể phân vùng bảng, chuyển đổi phân vùng và sau đó xử lý việc xóa.

Nhóm SQLCAT đã sử dụng kỹ thuật này trên thực tế thực sự khối lượng lớn dữ liệu. Tôi tìm thấy một số tài liệu tham khảo cho nó here nhưng tôi sẽ cố gắng và tìm thấy một cái gì đó dứt khoát hơn.

3

Nếu bạn có nhiều bàn phím ngoài, hãy bắt đầu ở cuối chuỗi và làm việc. Xóa cuối cùng sẽ nhanh hơn và chặn ít thứ hơn nếu không có bản ghi con nào để xóa tầng (mà tôi sẽ KHÔNG bật nếu tôi có một số lớn cho các bảng con vì nó sẽ giết hiệu năng).

Xóa theo lô.

Nếu bạn có bàn phím nước ngoài không còn được sử dụng nữa (bạn sẽ ngạc nhiên khi các bảng dữ liệu sản xuất kết thúc với các bảng cũ không ai thoát khỏi), loại bỏ chúng hoặc ít nhất là phá vỡ FK/PK kết nối. Không có ý nghĩa cheking một bảng cho hồ sơ nếu nó không được sử dụng.

Không xóa - đánh dấu các bản ghi là đã xóa và sau đó loại trừ các bản ghi được đánh dấu khỏi tất cả các truy vấn. Điều này được thiết lập tốt nhất tại thời điểm thiết kế cơ sở dữ liệu. Rất nhiều người sử dụng điều này bởi vì nó cũng là cách nhanh nhất để lấy lại hồ sơ vụ tai nạn đã bị xóa. Nhưng nó là rất nhiều công việc để thiết lập trong một hệ thống đã tồn tại.

1

Có các lần xóa và sau đó có các lần xóa. Nếu bạn đang lão hóa dữ liệu như là một phần của một công việc cắt, bạn hy vọng sẽ có thể xóa các khối liền nhau của các hàng bằng khóa nhóm. Nếu bạn phải già đi dữ liệu từ một bảng âm lượng cao mà không phải là tiếp giáp nó là rất rất đau đớn.

1

Nếu đúng là CẬP NHẬT nhanh hơn DELETES, bạn có thể thêm cột trạng thái được gọi là XÓA và lọc trên cột trong các lựa chọn của bạn. Sau đó chạy một proc vào ban đêm mà thực hiện xóa thực tế.

9

Tôi tự hỏi nếu đó là thời gian cho cơ sở dữ liệu thu thập rác? Bạn đánh dấu một hàng để xóa và máy chủ sẽ xóa nó sau này trong khi quét. Bạn sẽ không muốn điều này cho mỗi xóa - bởi vì đôi khi một hàng phải đi ngay bây giờ - nhưng nó sẽ có ích vào dịp.

+0

Tôi thích ý tưởng đó. Bạn có thể thực hiện điều này, chỉ cần đánh dấu một chút, To_be_delted và sau đó chạy một truy vấn thường xuyên để xóa một giá trị này. Nhưng tôi đồng ý rằng một hệ thống thu gom rác tự động sẽ được làm mát – Zapnologica

+2

Xóa một hàng có nghĩa là ít nhất ba điều: a) đảm bảo không có ràng buộc khoá ngoại nào bị vi phạm bởi việc xóa b) đánh dấu khoảng trống bị chiếm bởi hàng là "khả dụng". c) xóa hàng khỏi tất cả các chỉ mục trên bảng đó. Trong số này, a) có thể đắt nhất (nếu các bảng tham chiếu không có chỉ mục trên các cột khóa ngoại) nhưng cần được thực hiện ngay lập tức, vì vậy bạn có thể cho người dùng biết "bạn không thể xóa hàng này, nó vẫn còn tham chiếu ". b) có lẽ rẻ và c) thường không đắt. Do đó, tôi không tin vào ý tưởng này. –

4

Vấn đề là bạn chưa xác định đủ điều kiện của mình. I E. chính xác thì bạn đang tối ưu hóa cái gì?

Ví dụ: hệ thống có được bảo trì hàng đêm và không có người dùng nào trên hệ thống không?Và bạn đang xóa một phần lớn cơ sở dữ liệu?

Nếu ngoại tuyến và xóa một lượng lớn%, có thể có ý nghĩa khi chỉ cần tạo một bảng mới với dữ liệu cần giữ, thả bảng cũ và đổi tên. Nếu xóa một% nhỏ, bạn có thể muốn sắp xếp hàng loạt thành các lô lớn vì không gian đăng nhập của bạn cho phép. Nó hoàn toàn phụ thuộc vào cơ sở dữ liệu của bạn, nhưng việc giảm chỉ mục trong thời gian xây dựng lại có thể làm tổn thương hoặc giúp đỡ - nếu thậm chí có thể do bị "ngoại tuyến".

Nếu bạn đang trực tuyến, khả năng xóa của bạn xung đột với hoạt động của người dùng (và hoạt động của người dùng chủ yếu là đọc, cập nhật hoặc những gì)? Hoặc, bạn đang cố gắng tối ưu hóa trải nghiệm người dùng hoặc tốc độ nhận được truy vấn của mình? Nếu bạn đang xóa khỏi bảng thường xuyên được người dùng khác cập nhật, bạn cần phải thực hiện hàng loạt nhưng với kích thước lô nhỏ hơn. Ngay cả khi bạn làm một cái gì đó giống như một khóa bàn để thực thi cách ly, điều đó không làm tốt lắm nếu câu lệnh xóa của bạn mất một giờ.

Khi bạn xác định điều kiện của mình tốt hơn, bạn có thể chọn một trong các câu trả lời khác tại đây. Tôi thích liên kết trong bài viết của Rob Sanders để xếp hàng.

+0

cảm ơn matt. tốt, câu hỏi của tôi là khá chung chung, tôi đã có chậm xóa trong những dịp khác nhau và khác nhau, và điều này có nghĩa là một cách để thu thập những lời khuyên mọi người có thể chia sẻ về vấn đề này. – pomarc

1

Bạn có khóa ngoại có kích hoạt tính toàn vẹn tham chiếu không? Bạn có kích hoạt hoạt động không?

2

Tôi nghĩ rằng, bẫy lớn với xóa mà giết hiệu suất là sql sau mỗi hàng bị xóa, nó cập nhật tất cả các chỉ mục liên quan cho bất kỳ cột nào trong hàng này. những gì về delting tất cả các chỉ mục trước khi xóa hàng loạt?

5

Tóm tắt các câu trả lời qua 2014-11-05

Câu trả lời này được gắn cờ là wiki cộng đồng vì đây là một chủ đề ngày càng phát triển với rất nhiều sắc thái, nhưng rất ít câu trả lời có thể nói chung.

Vấn đề đầu tiên là bạn phải tự hỏi mình đang theo dõi tình huống nào? Đây thường là hiệu suất với một người dùng duy nhất trên db hoặc tỷ lệ với nhiều người dùng trên db. Đôi khi câu trả lời là đối diện chính xác.

Đối với người dùng duy nhất tối ưu hóa

  • Gợi ý một TABLELOCK
  • Remove chỉ số không được sử dụng trong xóa sau đó xây dựng lại chúng sau đó
  • hàng loạt sử dụng một cái gì đó giống như SET ROWCOUNT 20000 (hoặc bất cứ điều gì, tùy thuộc vào không gian log) và vòng lặp (có lẽ với WAITFOR DELAY) cho đến khi bạn loại bỏ tất cả (@@ROWCOUNT = 0)
  • Nếu xóa một số lượng lớn bảng, chỉ cần ma hãy chuyển sang bảng mới và xóa bảng cũ
  • Phân vùng các hàng cần xóa, sau đó thả phân đoạn.[Read more...]

Đối với đa người dùng tối ưu hóa

  • khóa Gợi ý hàng
  • Sử dụng chỉ số clustered
  • Thiết kế clustered index để giảm thiểu trang tổ chức lại nếu khối lớn được xóa
  • Cập nhật cột "is_deleted", sau đó xóa thực tế sau trong thời gian bảo trì

Đối với tối ưu hóa chung

  • Hãy chắc chắn FKS có chỉ số trên bảng nguồn của họ
  • Hãy chắc chắn WHERE khoản có chỉ số
  • Xác định các hàng để xóa trong mệnh đề WHERE với một cái nhìn hoặc có nguồn gốc thay vì tham chiếu trực tiếp vào bảng. [Read more...]
-1

Đơn giản hóa việc sử dụng các chức năng trong mệnh đề WHERE của bạn! Ví dụ:

DELETE FROM Claims 
WHERE dbo.YearMonthGet(DataFileYearMonth) = dbo.YearMonthGet(@DataFileYearMonth) 

Điều khoản của yêu cầu WHERE yêu cầu 8 phút để xóa 125.837 bản ghi.

Chức năng YearMonthGet bao gồm ngày có năm và tháng kể từ ngày nhập và đặt day = 1. Điều này là để đảm bảo chúng tôi đã xóa hồ sơ dựa trên năm và tháng nhưng không phải ngày trong tháng.

Tôi viết lại mệnh đề WHERE để:

WHERE YEAR(DataFileYearMonth) = YEAR(@DataFileYearMonth) 
AND MONTH(DataFileYearMonth) = MONTH(@DataFileYearMonth) 

Kết quả: Các yêu cầu về xóa 38-44 giây để xóa những 125.837 hồ sơ!