Điều gì tốt hơn cho những thay đổi lớn đối với một bảng: XÓA và XÓA mỗi lần hoặc CẬP NHẬT?


27

Tôi đang thực hiện một dự án mà tôi cần thay đổi khoảng 36K hồ sơ trong một bảng mỗi ngày. Tôi đang tự hỏi điều gì sẽ thực hiện tốt hơn:

  1. xóa hàng và chèn cái mới, hoặc
  2. cập nhật các hàng đã có

Đối với tôi, việc xóa tất cả các hàng và chèn các hàng mới sẽ dễ dàng hơn, nhưng nếu điều này sẽ phân mảnh bảng và các chỉ mục và hiệu suất tác động thì tôi muốn thực hiện cập nhật khi có thể và chỉ xóa / chèn khi cần thiết.

Đây sẽ là một dịch vụ hàng đêm và tôi không muốn cải thiện tốc độ của chính quá trình này. Tôi quan tâm nhiều hơn đến hiệu suất của các truy vấn đối với bảng này nói chung khi tôi đã có 89 triệu bản ghi và quá trình hàng đêm này sẽ ảnh hưởng đến nó như thế nào.

Tôi có nên xóa / chèn hồ sơ hay tôi nên cập nhật những bản ghi hiện có (nếu có thể) cho quy trình hàng đêm này?


Tôi tin rằng bạn nên cung cấp thêm chi tiết trên bảng của mình, vì tôi đoán nó sẽ phụ thuộc vào sự tồn tại tiềm năng của các chỉ số trên các trường.
SRKX

Câu trả lời:


9

Nó thực sự phụ thuộc vào bao nhiêu dữ liệu đang thay đổi. Hãy nói rằng bảng này có 20 cột. Và bạn cũng có 5 chỉ mục - mỗi chỉ số khác nhau. cột.

Bây giờ nếu các giá trị trong tất cả 20 cột đang thay đổi HOẶC ngay cả khi dữ liệu trong 5 cột thay đổi và 5 cột này đều được lập chỉ mục, thì bạn có thể nên "xóa và chèn" tốt hơn. Nhưng nếu chỉ có 2 cột thay đổi và giả sử đây không phải là một phần của bất kỳ chỉ mục không được phân cụm nào, thì bạn có thể nên "Cập nhật" các bản ghi vì trong trường hợp này chỉ có chỉ mục được nhóm sẽ được cập nhật (và các chỉ mục sẽ không phải đã được cập nhật).


Trong nghiên cứu sâu hơn, tôi thấy rằng nhận xét trên của tôi là không cần thiết vì SQL Server bên trong có 2 cơ chế riêng biệt để thực hiện CẬP NHẬT. - "Cập nhật tại chỗ" (nghĩa là bằng cách thay đổi giá trị cột thành mới trong hàng ban đầu) hoặc dưới dạng "CẬP NHẬT không tại chỗ" (XÓA theo sau là CHERTN).

Cập nhật tại chỗ là quy tắc và được thực hiện nếu có thể. Ở đây các hàng giữ chính xác tại cùng một vị trí trên cùng một trang trong cùng một phạm vi. Chỉ các byte bị ảnh hưởng được chnaged. Tlog chỉ có một bản ghi (miễn là không có kích hoạt cập nhật). Cập nhật xảy ra tại chỗ nếu một đống đang được cập nhật (và có đủ không gian trên trang). Các cập nhật cũng xảy ra nếu phím phân cụm thay đổi nhưng hàng không cần phải di chuyển.

Ví dụ: nếu bạn có một chỉ mục được nhóm trên tên cuối cùng và bạn có các tên: Able, Baker, Charlie Bây giờ bạn muốn cập nhật Baker thành Becker. Không có hàng phải được di chuyển. Vì vậy, điều này có thể diễn ra. Trong khi đó, nếu bạn phải cập nhật Able to Kumar, các hàng sẽ phải được thay đổi (mặc dù chúng sẽ nằm trên cùng một trang). Trong trường hợp này, SQL Server sẽ thực hiện XÓA sau đó là một CHERTN.

Xem xét ở trên, tôi sẽ đề nghị bạn thực hiện CẬP NHẬT bình thường và để SQL Server tìm ra cách tốt nhất để làm điều đó trong nội bộ.

Để biết thêm chi tiết về nội bộ "CẬP NHẬT" hoặc về vấn đề đó đối với bất kỳ nội bộ liên quan đến Máy chủ SQL nào, hãy xem cuốn sách của Kalen Delaney, Paul Randal, et al. - SQL Server 2008 Internals .


8

Bạn đã điều tra lệnh MERGE trong SQL 2008 chưa? Đây là một ví dụ cơ bản:

  merge YourBigTable ybt
  using (select distinct (RecordID) from YourOtherTable) yot
     on yot.Recordid = YBT.RecordID
  when NOT matched by target
  then  insert (RecordID)
        values (yot.DeviceID) ;

Về cơ bản, đây là lệnh "UPSERT". Cập nhật nếu nó tồn tại, chèn nó nếu nó không. RẤT nhanh, lệnh rất mát mẻ.


1
Nó không nhanh hơn CẬP NHẬT, cùng một cơ chế dưới mui xe.
Mark Storey-Smith

Nó nhanh hơn cập nhật sau đó chèn những cái chưa tồn tại.
datagod

2
Nếu bạn biết đó là trường hợp, hãy chứng minh điều đó :)
Mark Storey-Smith

4

Nhưng, bản thân tôi đã kiểm tra Xóa và Chèn so với Cập nhật trên bảng có bản ghi 30 triệu (3crore). Bảng này có một khóa tổng hợp duy nhất được nhóm và 3 khóa Không tách rời. Để xóa và chèn, phải mất 9 phút. Để cập nhật, phải mất 55 phút. Chỉ có một cột được cập nhật trong mỗi hàng.

Vì vậy, tôi yêu cầu bạn mọi người không đoán. Các phương trình sẽ thay đổi khi xử lý bảng lớn có nhiều cột và có nhiều dữ liệu.


Tôi cũng đã gặp trường hợp này nhưng sau đó phát hiện ra rằng đôi khi có thể tối ưu hóa một sự hợp nhất lớn bằng cách thêm các chỉ báo (temp hoặc perm) vào nguồn hoặc đích, gợi ý hoặc đặt phụ mục tiêu (không áp dụng cho hợp nhất hoàn toàn).
crokusek

3

Cập nhật không nhanh bằng. Mẹo nhỏ để đạt được một thao tác chèn nhanh là vô hiệu hóa các chỉ mục trong khi dữ liệu đang được chèn.

Cân nhắc sử dụng cái này:

-- disable indexes
ALTER INDEX [index_name] ON dbo.import_table DISABLE
-- ... disable more indexes

-- don't use delete if you don't care about minimal logging. truncate is faster
TRUNCATE TABLE dbo.import_table

-- just insert the new rows
INSERT dbo.import_table
SELECT
    *
FROM
    dbo.source_table

-- rebuild indexes
ALTER INDEX [index_name] ON dbo.import_table REBUILD
-- ... rebuild more indexes

Thậm chí nhanh hơn là tắt cập nhật thống kê tự động trong các tùy chọn db. Nếu bảng được thay đổi đáng kể, bạn nên chạy:

UPDATE STATISTICS dbo.import_table

hoặc là

EXEC sp_updatestats

như một công việc thường xuyên (hàng ngày, hàng tuần tùy thuộc vào kích thước db) để giữ cho các số liệu thống kê được cập nhật. Điều cần chú ý là cập nhật số liệu thống kê khi bảng trống. Điều đó sẽ làm tăng số liệu thống kê nếu bạn không chạy nó sau khi bảng được điền lại.


4
Tôi không đồng ý rằng đây luôn là trường hợp. Ngoài ra, bảng trong câu hỏi của @ acceptilot không thể bị xóa bởi TRUNCATE vì nó chứa 89 triệu bản ghi và anh ta chỉ muốn cập nhật 36k.
Mark Storey-Smith

Cần học cách đọc bài cẩn thận hơn! Tôi sẽ cập nhật bài viết ... thực sự, tôi cần thay đổi nhiều.
Asken
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.