2010-08-10 46 views
5

Tôi có cơ sở dữ liệu SQL Server 2005 và tôi đã thử đặt chỉ mục trên các trường thích hợp để tăng tốc độ DELETE bản ghi từ bảng với hàng triệu hàng (big_table chỉ có 3 cột) , nhưng giờ là thời gian thực hiện DELETE thậm chí còn dài hơn! (Ví dụ: 1 giờ so với 13 phút)SQL Server DELETE chậm hơn với chỉ mục

Tôi có mối quan hệ giữa các bảng và cột mà tôi lọc DELETE của mình ở trong bảng khác. Ví dụ

DELETE FROM big_table 
WHERE big_table.id_product IN (
SELECT small_table.id_product FROM small_table 
WHERE small_table.id_category = 1) 

Btw, tôi cũng đã cố gắng:

DELETE FROM big_table 
WHERE EXISTS 
(SELECT 1 FROM small_table 
WHERE small_table.id_product = big_table.id_product 
AND small_table.id_category = 1) 

và trong khi nó có vẻ chạy nhanh hơn một chút so với lần đầu tiên, nó vẫn còn chậm hơn rất nhiều với các chỉ số so với khi không.

Tôi tạo ra chỉ số trên các lĩnh vực:

  1. big_table.id_product
  2. small_table.id_product
  3. small_table.id_category

tập tin .LDF tôi phát triển rất nhiều trong DELETE.

Tại sao các truy vấn của tôi chậm hơn khi tôi có chỉ mục trên bảng? Tôi nghĩ rằng chúng được cho là chạy nhanh hơn.

CẬP NHẬT

Được rồi, được sự đồng thuận có vẻ là chỉ số sẽ chậm lại một khổng lồ DELETE bởi vì chỉ số này phải được cập nhật. Mặc dù, tôi vẫn không hiểu tại sao nó không thể DELETE tất cả các hàng cùng một lúc và chỉ cập nhật chỉ mục một lần ở cuối.

Tôi đã theo ấn tượng từ một số đọc của tôi rằng các chỉ mục sẽ tăng tốc độ DELETE bằng cách thực hiện tìm kiếm các trường trong mệnh đề WHERE nhanh hơn.

Odetocode.com says:

"Chỉ số làm việc cũng như khi tìm kiếm một bản ghi trong lệnh DELETE và UPDATE như họ làm cho câu lệnh SELECT."

Nhưng sau đó trong bài báo, nó nói rằng quá nhiều chỉ mục có thể làm tổn thương hiệu suất.

Câu trả lời cho Bobs câu hỏi:

  1. 55 triệu hàng trong bảng
  2. 42 triệu hàng bị xóa
  3. tương tự SELECT tuyên bố sẽ không chạy (Exception của loại 'System.OutOfMemoryException' đã được ném)

tôi đã cố gắng 2 truy vấn sau đây:

SELECT * FROM big_table 
WHERE big_table.id_product IN (
SELECT small_table.id_product FROM small_table 
WHERE small_table.id_category = 1) 

SELECT * FROM big_table 
INNER JOIN small_table 
ON small_table.id_product = big_table.id_product 
WHERE small_table.id_category = 1 

Cả thất bại sau khi chạy 25 phút với thông điệp này lỗi từ SQL Server 2005:

An error occurred while executing batch. Error message is: Exception of type 'System.OutOfMemoryException' was thrown. 

Máy chủ cơ sở dữ liệu là một máy Xeon lõi kép cũ hơn với RAM 7,5 GB. Đó là cơ sở dữ liệu thử nghiệm đồ chơi của tôi :) vì vậy nó không chạy bất cứ thứ gì khác.

Tôi có cần phải làm gì đó đặc biệt với chỉ mục của mình sau khi tôi CREATE để chúng hoạt động bình thường không?

+3

có bao nhiêu hàng trong bảng? Có bao nhiêu hàng đang bị xóa? Câu lệnh SELECT tương tự sẽ mất bao lâu? Việc biết câu lệnh SELECT nhanh đến mức nào có thể cung cấp một số thông tin chi tiết về cách các chỉ mục ảnh hưởng đến DELETE như thế nào. – bobs

+0

55 mil hàng, 42 đã xóa, không hoàn thành, xem ở trên để biết thêm chi tiết – JohnB

+0

Mất nhiều thời gian hơn vì khi bạn thực hiện xóa, các chỉ mục tham chiếu đến bảng của bạn cũng phải được cập nhật. – WOPR

Trả lời

27

Chỉ mục giúp tra cứu nhanh hơn - như chỉ mục ở mặt sau của sách.

Các hoạt động thay đổi dữ liệu (như DELETE) chậm hơn, vì chúng liên quan đến thao tác các chỉ mục. Hãy xem xét cùng một chỉ mục ở mặt sau của cuốn sách. Bạn có nhiều việc phải làm nếu bạn thêm, xóa hoặc thay đổi các trang vì bạn cũng phải cập nhật chỉ mục.

0

Bạn cũng có thể thử mở rộng TSQL để DELETE cú pháp và kiểm tra xem nó cải thiện hiệu suất:

DELETE FROM big_table 
FROM big_table AS b 
INNER JOIN small_table AS s ON (s.id_product = b.id_product) 
WHERE s.id_category =1 
+0

Điều này không giúp gì cả; nó mất chính xác cùng một thời gian như 'xóa từ big_table nơi tồn tại (chọn 1 từ small_table nơi small_table.id_product = big_table.id_product và small_table.id_category = 1)' – JohnB

1

I Agree với Bobs bình luận trên - nếu bạn đang xóa khối lượng lớn dữ liệu từ các bảng lớn xóa các chỉ số có thể mất một thời gian trên đầu trang của xóa dữ liệu chi phí của nó làm kinh doanh mặc dù. Vì nó xóa tất cả các dữ liệu ra bạn đang gây ra sự kiện reindexing xảy ra.

Liên quan đến tăng trưởng logfile; nếu bạn không làm bất cứ điều gì với logfiles của bạn, bạn có thể chuyển sang ghi nhật ký Simple; nhưng tôi yêu cầu bạn đọc về tác động có thể có trên bộ phận CNTT của bạn trước khi bạn thay đổi.

Nếu bạn cần thực hiện xóa trong thời gian thực; thường là một công việc tốt để gắn cờ dữ liệu không hoạt động trực tiếp trên bảng hoặc trong một bảng khác và loại trừ dữ liệu đó khỏi các truy vấn; sau đó quay lại sau và xóa dữ liệu khi người dùng không nhìn chằm chằm vào đồng hồ cát. Có một lý do thứ hai để giải quyết vấn đề này; nếu bạn đang xóa rất nhiều dữ liệu ra khỏi bảng (đó là những gì tôi đang giả sử dựa trên vấn đề logfile của bạn) thì bạn có thể sẽ muốn làm một indexdefrag để reorgnaise chỉ mục; làm điều đó ngoài giờ là cách để đi nếu bạn không thích người dùng trên điện thoại!

0

JohnB đang xóa khoảng 75% dữ liệu. Tôi nghĩ rằng sau đây sẽ là một giải pháp có thể và có lẽ là một trong những giải pháp nhanh hơn. Thay vì xóa dữ liệu, hãy tạo một bảng mới và chèn dữ liệu mà bạn cần giữ lại. Tạo các chỉ mục trên bảng mới sau khi chèn dữ liệu. Bây giờ thả bảng cũ và đổi tên bảng mới thành tên cũ như cũ.

Giả định trên giả định rằng có đủ dung lượng đĩa để lưu trữ tạm thời dữ liệu trùng lặp.

0

Hãy thử một cái gì đó như thế này để tránh số lượng lớn xóa (và do đó tránh log tăng trưởng tập tin)

declare @continue bit = 1 

-- delete all ids not between starting and ending ids 
while @continue = 1 
begin 

    set @continue = 0 

    delete top (10000) u 
    from <tablename> u WITH (READPAST) 
    where <condition> 

    if @@ROWCOUNT > 0 
     set @continue = 1 

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