Máy chủ SQL SQL Bảng trống có chậm không sau khi xóa tất cả (12 triệu) bản ghi?


27

Tôi có một phiên bản SQL Server 2008 với khoảng 150 cột. Trước đây tôi đã điền vào bảng này với khoảng 12 triệu mục, nhưng kể từ đó đã xóa bảng để chuẩn bị cho một bộ dữ liệu mới.

Tuy nhiên, lệnh rằng một khi ran ngay lập tức trên một bảng trống như count(*)select top 1000SQL Management Studiobây giờ mất kiếp để chạy.

SELECT COUNT(*) FROM TABLE_NAME 

mất hơn 11 phút để trả về 0 và SELECT TOP 1000mất gần 10 phút để trả lại một bảng trống.

Tôi cũng nhận thấy rằng không gian trống trên ổ cứng của tôi đã biến mất theo nghĩa đen (giảm từ khoảng 100G xuống 20G). Điều duy nhất xảy ra giữa là một truy vấn duy nhất tôi đã chạy:

DELETE FROM TABLE_NAME

Có gì trên thế giới đang diễn ra?!?


5
Cơ sở dữ liệu của bạn sử dụng mô hình phục hồi nào? Nếu là "Đầy đủ", phiên bản SQL của bạn sẽ lưu trữ một bản ghi của tất cả những lần xóa đó, có thể là nơi không gian trống của bạn đã đi. Nếu khôi phục hoàn toàn là một yêu cầu, tôi khuyên bạn nên sử dụng TRUNCATE TABLEthay vì DELETE FROM.
Tullo_x86

2
150 cột? Bảng đó thể quá đầy - hầu hết các bộ dữ liệu nên nhỏ hơn nhiều. Không thể nói mà không có bối cảnh đầy đủ, tuy nhiên.
Clockwork-Muse

Câu trả lời:


42

Bạn đã được nói về lý do tại sao TRUNCATEsẽ nhanh hơn / tốt hơn / quyến rũ hơn nhiều DELETE, nhưng vẫn còn một câu hỏi để giải quyết:

Tại sao SELECTchậm hơn sau khi DELETE hoàn thành ?

Đó là bởi vì DELETEchỉ có bóng mờ các hàng. Bảng chỉ lớn như khi nó có 12M hàng, mặc dù nó không có. Để đếm các hàng (0), phải mất nhiều thời gian để đếm 12M hàng. Trong thời gian, quy trình dọn dẹp ma sẽ thu thập các bản ghi ma này và xử lý các trang chỉ chứa ma và các CHỌN của bạn sẽ tăng tốc. Nhưng ngay bây giờ nếu bạn kiểm tra Skipped Ghosted Records/sectrong perfmon có lẽ đang tăng vọt trong thời gian SELECT COUNT(*). Bạn cũng có thể tăng tốc mọi thứ bằng cách xây dựng lại bảng : ALTER TABLE ... REBUILD.

TRUNCATE cũng sẽ quan tâm đến vấn đề này, vì nó không để lại ma.

Xem thêm Bên trong Storage Engine: Ghost dọn dẹp chuyên sâu .


13

DELETEbáo cáo xóa từng hàng từ một bảng một lần, ghi nhật ký từng hàng trong transaction log, cũng như duy trì log sequence number (LSN)thông tin. Vì bạn đã đề cập đến bảng của mình có dữ liệu rất lớn (12 triệu bản ghi), sau khi xóa đĩa cứng của bạn hết dung lượng, hãy kiểm tra kích thước của tệp Nhật ký cơ sở dữ liệu của bạn. Nó có thể đã phát triển nhất.

một cách tốt hơn sẽ có được:

TRUNCATE TABLE_NAME

2
+1, hoàn toàn giống với Oracle DB. Nếu bạn sử dụng các câu lệnh gây ra các bản ghi để ghi nhật ký, nó sẽ làm chậm cơ sở dữ liệu theo thời gian.
Petro Semeniuk

@PetroSemeniuk Từ những gì tôi nhớ trên Oracle, hãy để lại dấu hiệu nước cao một mình, cắt cụt sẽ thiết lập lại dấu hiệu nước cao. Tôi tin rằng bất kỳ hoạt động nào yêu cầu quét toàn bộ sẽ quét các khối cho đến khi mực nước cao. Do đó xóa có thể hỗ trợ các hoạt động được lập chỉ mục, nhưng không quét. TRUNCATE là hoạt động đúng.
Glenn

3

(Đây ban đầu là một nhận xét cho câu trả lời của @ DaveE, nhưng tôi đã đưa nó vào câu trả lời của riêng mình vì nó đã dài)

TRUNCATE một hoạt động đăng nhập. Mặt khác, nó phải không tuân thủ ACID. Tuy nhiên, sự khác biệt giữa TRUNCATEDELETE:

  • Sử dụng không gian TRUNCATEnhật ký : chỉ ghi nhật ký trang / phạm vi * được giải phóng, trong khi DELETEghi nhật ký từng hàng riêng lẻ.
  • Sử dụng khóa: TRUNCATEthường sẽ sử dụng ít khóa hơn, vì nó cần khóa bảng và khóa trang, trái ngược với việc DELETEsử dụng khóa hàng **.
  • IDENTITYtrình tự: TRUNCATEđặt lại trình tự nhận dạng trên một bảng, nếu có.

(* Một phạm vi = 8 trang. TRUNCATESẽ ghi / xóa các phạm vi nếu tất cả chúng đều nằm trong một bảng đó, nếu không, nó sẽ ghi / xóa các trang khỏi các phạm vi hỗn hợp.

** Một tác dụng phụ của việc này là DELETE FROM TABLEcó khả năng để lại các trang trống được phân bổ cho bảng, tùy thuộc vào việc thao tác có thể có khóa bảng độc quyền hay không.)

Vì vậy (trở lại câu hỏi ban đầu), TRUNCATE TABLEsẽ tốt hơn so với việc DELETE FROM TABLEbạn làm trống bảng nhưng muốn giữ cấu trúc (NB: TRUNCATEkhông thể được sử dụng trên một bảng được tham chiếu bởi khóa ngoại từ bảng khác).

Như đã lưu ý trong nhận xét của @ Tullo, cũng kiểm tra mô hình khôi phục cơ sở dữ liệu của bạn - nếu nó đầy đủ, thì bạn cần phải bắt đầu sao lưu nhật ký hoặc thay đổi mô hình khôi phục của mình thành đơn giản. Khi bạn đã thực hiện một trong những người, có thể bạn sẽ muốn thu nhỏ log file của bạn như một lần-off hoạt động (NB: log file chỉ ) để đòi lại tất cả những gì không gian trống.

Cuối cùng, một điều khác cần lưu ý - thống kê bảng. chạy UPDATE STATISTICS <TABLENAME>' afterTRUNCATE /DELETE` để trình tối ưu hóa truy vấn không bị tăng gấp ba bởi các thống kê cũ.


2

(LƯU Ý: Tôi không phải là DBA) XÓA là một hoạt động được ghi lại và nó không giải phóng không gian sử dụng. Bạn có thể có một nhật ký giao dịch lớn chiếm không gian và quét bảng chạy trên không gian bảng 'trống'. Tôi đoán bạn cần xóa nhật ký giao dịch và thu nhỏ cơ sở dữ liệu của bạn. Bài viết StackOverflow này sẽ giúp bạn bắt đầu.

Và sử dụng BẢNG TRUNCATE khi bạn muốn làm điều này trong tương lai.

EDIT: Tuyên bố của tôi về TRUNCATE không được đăng nhập là do lỗi. loại bỏ.

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.