2010-04-12 41 views
8

Tôi đang thử nghiệm tốc độ chèn nhiều hàng với một câu lệnh INSERT duy nhất.Nhiều hàng với một INSERT duy nhất trong SQLServer 2008

Ví dụ: INSERT INTO [MyTable] GIÁ TRỊ (5, 'chó'), (6, 'mèo'), (3, 'cá)

này rất nhanh cho đến khi tôi vượt qua 50 hàng trên một tuyên bố duy nhất, sau đó tốc độ giảm đáng kể.

Chèn 10.000 hàng với các lô 50 mất 0,9 giây. Chèn 10.000 hàng với các lô 51 mất 5,7 giây.

Câu hỏi của tôi có hai phần:

  1. Tại sao lại có sự sụt giảm hiệu suất cứng ở 50?
  2. Tôi có thể dựa vào hành vi này và viết mã ứng dụng của mình để không bao giờ gửi các lô lớn hơn 50 không?

Thử nghiệm của tôi được thực hiện bằng C++ và ADO.

Chỉnh sửa: Dường như điểm thả không phải là 50 hàng, nhưng 1000 cột. Tôi nhận được kết quả tương tự với 50 hàng 20 cột hoặc 100 hàng của 10 cột.

+0

tôi có cảm giác rằng nó trở nên tồi tệ hơn do phân tích cú pháp đầu vào. – Andrey

+2

Hoàn thành và tổng số đoán hoang dã: ít hơn 50 hàng được lưu trữ trong bộ nhớ RAM của SQL Server, nhưng chèn lớn hơn được coi là "quan trọng" hơn và được ghi ra đĩa ngay lập tức? Trung thực không chắc chắn (Do đó bình luận thay vì trả lời) –

Trả lời

0

Bạn cũng có so sánh với phương pháp "liên minh tất cả" được hiển thị ở đây không? http://blog.sqlauthority.com/2007/06/08/sql-server-insert-multiple-records-using-one-insert-statement-use-of-union-all/

Tôi nghi ngờ có bộ nhớ cache/chỉ mục nội bộ được sử dụng tối đa 50 hàng (đó là số thập phân tròn đẹp). Sau 50 hàng nó rơi trở lại trên một thuật toán chèn trường hợp tổng quát ít hiệu quả hơn, có thể xử lý số lượng đầu vào tùy ý mà không cần sử dụng bộ nhớ quá mức.

+0

Chỉ cần thử cách tiếp cận UNION ALL. Nó cũng khá chậm. Khoảng 7 giây cho 10000 hàng. – Todd

0

sự chậm lại có lẽ là phân tích cú pháp của các giá trị chuỗi: VALUES (5, 'dog'), (6, 'cat'), (3, 'fish) chứ không phải vấn đề INSERT.

thử một cái gì đó như thế này, mà sẽ chèn một hàng cho mỗi hàng được trả về bởi truy vấn:

INSERT INTO YourTable1 
    (col1, col2) 
    SELECT 
     Value1, Value2 
     FROM YourTable2 
     WHERE ...--rows will be more than 50 

và xem những gì sẽ xảy ra

0

Nếu bạn đang sử dụng SQL 2008, sau đó bạn có thể sử dụng giá trị bảng các tham số và chỉ cần thực hiện một câu lệnh chèn đơn.

cá nhân, tôi chưa bao giờ thấy sự chậm lại ở mức 50 bản ghi chèn ngay cả với các lô thông thường. Bất kể chúng tôi đã chuyển sang các thông số giá trị bảng có tốc độ tăng đáng kể cho chúng tôi.

+0

Tôi đã thử điều này, và là một người mới làm quen với SQL, tôi không chắc chắn tôi đang làm nó theo cách tối ưu nhất. Tuy nhiên các thử nghiệm của tôi hiển thị ở bất cứ đâu từ 6 giây đến 30 giây cho mỗi 10000 hàng, tùy thuộc vào kích cỡ lô. Không có gì gần với câu lệnh INSERT nhiều hàng. – Todd

+0

Điều đó rất lạ. Bạn có gán tất cả các trường trong bảng hoặc một số trường được gán thông qua các giá trị mặc định của cột không? Nếu sau này, chúng có thể tốn kém (như hàm getdate()) ... – NotMe

+0

Tôi theo ví dụ ở đây: http://msdn.microsoft.com/en-us/library/bb510489%28SQL.100%29. aspx Nhưng thay vì chèn vào bảng tạm thời từ một bảng khác, tôi chèn các giá trị bằng cách sử dụng chèn nhiều hàng. Tôi chỉ định tất cả các giá trị, không có giá trị mặc định. – Todd

0

suy nghĩ ngẫu nhiên:

  • là nó hoàn toàn phù hợp khi chạy liên tục?
  • bạn có đang kiểm tra các mục trùng lặp trong hàng 10k đầu tiên cho lần chèn 10k thứ 2 không?
  • bạn có thử kích thước hàng loạt là 51 trước không?
  • bạn có làm trống bảng giữa các lần kiểm tra không?
+0

Có nó rất nhất quán. Và tôi làm trống bảng giữa mọi thử nghiệm. – Todd

+0

@Todd: thú vị. Câu hỏi hay. Và tôi không còn ý tưởng nào nữa :-) – gbn

2

Nó cũng có thể liên quan đến kích thước của hàng. Bảng bạn sử dụng làm ví dụ dường như chỉ có 2 cột. Điều gì xảy ra nếu nó có 25 cột? Hiệu suất có giảm xuống ở 50 hàng không?

+0

Thú vị. Bảng trên chỉ là một ví dụ, bảng thực tế của tôi có 20 cột trong đó. Tôi cắt giảm xuống 10 và thử lại. Bây giờ tôi nhận được cắt giảm ở 100. Lô 100 mất khoảng 0,6 giây. Các lô 101 mất khoảng 3,25 giây. Dường như giới hạn không phải là 50 hàng, mà là 1000 trường được cập nhật riêng lẻ? – Todd

+0

Có vẻ như việc cắt giảm giống như tổng dữ liệu trong bộ nhớ. Nếu một bảng nhỏ, thì có lẽ bạn có thể phù hợp với 100 hàng thành một "khối", bất kể khối nào là. Nhưng các bảng lớn, có nhiều cột hoặc có vài cột lớn (ví dụ: VARCHAR (1200)) sẽ giới hạn số hàng bạn có thể vừa với một khối. – MJB

0

Để chèn khối lượng lớn và tần số cao, hãy xem xét sử dụng Bulk Inserts để tải dữ liệu của bạn. Không phải điều đơn giản nhất trong thế giới mà anh ta thực hiện và nó mang lại cho nó một bộ thách thức mới, nhưng nó có thể nhanh hơn nhiều so với thực hiện một INSERT.

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