2009-04-15 37 views
26

Tôi cố gắng chèn hàng triệu bản ghi vào bảng có hơn 20 chỉ mục.Chèn hàng loạt chậm cho bảng có nhiều chỉ mục

Về lâu cuối cùng phải mất hơn 4 giờ mỗi 100.000 hàng, và truy vấn đã bị hủy bỏ sau khi 3½ ngày ...

Bạn có bất cứ lời đề nghị về làm thế nào để tăng tốc độ này lên.

(tôi nghi ngờ các chỉ số nhiều là nguyên nhân Nếu bạn cũng nghĩ như vậy, làm thế nào tôi có thể tự động thả chỉ số trước khi phẫu thuật, và sau đó tạo ra các chỉ số tương tự sau đó một lần nữa.?)

thông tin thêm:

  • Không gian được sử dụng bởi các chỉ mục khoảng 4 lần không gian được sử dụng bởi dữ liệu riêng lẻ
  • Chèn được gói trong một giao dịch trên 100.000 hàng.

Cập nhật trên status:

Câu trả lời được chấp nhận giúp tôi làm cho nó nhanh hơn nhiều.

Trả lời

41

Bạn có thể tắt và bật chỉ mục. Lưu ý rằng việc vô hiệu hóa chúng có thể có các tác dụng phụ không mong muốn (chẳng hạn như có các khóa chính trùng lặp hoặc các chỉ mục duy nhất, v.v.) sẽ chỉ được tìm thấy khi kích hoạt lại các chỉ mục.

--Disable Index 
ALTER INDEX [IXYourIndex] ON YourTable DISABLE 
GO 

--Enable Index 
ALTER INDEX [IXYourIndex] ON YourTable REBUILD 
GO 
+8

Có thể muốn không tắt chỉ mục PK (và chắc chắn không phải nếu được nhóm). – Richard

+0

Vâng, bạn nói đúng. Cảm ơn bạn đã chỉ ra điều đó. – Lucero

+2

@Lucero: Cảm ơn câu trả lời này. Một gợi ý: Có thể cập nhật câu trả lời của bạn theo bình luận của Richard? –

7

Điều này nghe giống như hoạt động kho dữ liệu. Nó sẽ là bình thường để thả các chỉ mục trước khi chèn và xây dựng lại chúng sau đó.

Khi bạn xây dựng lại các chỉ mục, trước tiên hãy xây dựng chỉ mục nhóm và ngược lại sẽ thả chỉ mục. Tất cả họ đều nên điền vào 100%.

Mã nên một cái gì đó như thế này

if object_id('Index') is not null drop table IndexList 
select name into Index from dbo.sysindexes where id = object_id('Fact') 

if exists (select name from Index where name = 'id1') drop index Fact.id1 
if exists (select name from Index where name = 'id2') drop index Fact.id2   
if exists (select name from Index where name = 'id3') drop index Fact.id3 
. 
. 
BIG INSERT 

RECREATE THE INDEXES 
4

Theo ghi nhận của một câu trả lời vô hiệu hóa các chỉ số sẽ là một khởi đầu rất tốt.

4 giờ trên 100.000 hàng [...] Chèn được gói trong giao dịch trên 100.000 hàng.

Bạn nên xem xét giảm số lượng, máy chủ phải duy trì số lượng lớn trạng thái trong khi giao dịch (để có thể cuộn lại), điều này (cùng với chỉ mục) có nghĩa là việc thêm dữ liệu rất khó công việc.

Tại sao không bao bọc từng câu lệnh chèn trong giao dịch của riêng mình?

Ngoài ra, hãy xem bản chất của SQL bạn đang sử dụng, bạn có thêm một hàng cho mỗi câu lệnh (và vòng kết nối mạng) hay thêm nhiều?

+0

Cảm ơn câu trả lời và cho các câu hỏi bổ sung. Chèn số lượng lớn đang xảy ra với một cuộc gọi duy nhất đến một thủ tục được lưu trữ. –

+1

Tôi nghĩ rằng một liên kết đến câu trả lời khác bằng cách sử dụng chỉ href = "# 751062" tránh tải lại trang. –

+0

@Ole: Cảm ơn ý tưởng về liên kết liên kết (hiển nhiên là nhìn lại :-)). – Richard

3

Tắt và sau đó bật lại chỉ mục thường được đề xuất trong những trường hợp đó. Tôi có những nghi ngờ của tôi về cách tiếp cận này mặc dù, bởi vì:

(1) Người dùng DB của ứng dụng cần các đặc quyền sửa đổi lược đồ, mà nó thường không nên có. (2) Cách tiếp cận chèn và/hoặc lược đồ chỉ mục có thể ít hơn thì tối ưu ở vị trí đầu tiên, nếu không xây dựng lại cây chỉ mục hoàn chỉnh sẽ không nhanh hơn sau đó chèn hàng loạt (ví dụ: khách hàng đưa ra một câu lệnh chèn vào một thời điểm, gây ra hàng nghìn vòng tròn máy chủ hoặc một lựa chọn nghèo trên chỉ mục nhóm, dẫn đến việc chia tách nút chỉ mục không đổi).

Đó là lý do gợi ý của tôi trông hơi khác một chút:

  • Tăng ADO.NET BatchSize
  • Chọn clustered index bảng mục tiêu một cách khôn ngoan, để chèn sẽ không dẫn đến chia rẽ nút clustered index. Thông thường, cột nhận dạng là một lựa chọn tốt
  • Để khách hàng chèn vào bảng heap tạm thời trước tiên (bảng heap không có bất kỳ chỉ mục nhóm nào); sau đó, vấn đề cái lớn "chèn-vào-chọn" tuyên bố để đẩy tất cả những gì dữ liệu bảng dàn vào bảng mục tiêu thực tế
  • Áp dụng SqlBulkCopy
  • ghi giao dịch Giảm bằng cách chọn mô hình phục hồi số lượng lớn-đăng

Bạn có thể tìm thêm thông tin bị hủy trong this article.

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