2011-02-01 30 views
5

tôi có như sau (đơn giản hóa) mã mà tôi muốn tối ưu hóa cho tốc độ:C# Tối ưu hóa: Chèn 200 triệu hàng vào cơ sở dữ liệu

long inputLen = 50000000; // 50 million 
DataTable dataTable = new DataTable(); 
DataRow dataRow; 
object[] objectRow; 
while (inputLen--) 
{ 
    objectRow[0] = ... 
    objectRow[1] = ... 
    objectRow[2] = ... 

    // Generate output for this input 
    output = ... 

    for (int i = 0; i < outputLen; i++) // outputLen can range from 1 to 20,000 
    { 
     objectRow[3] = output[i]; 
     dataRow = dataTable.NewRow(); 
     dataRow.ItemArray = objectRow; 
     dataTable.Rows.Add(dataRow); 
    } 
} 

// Bulk copy 
SqlBulkCopy bulkTask = new SqlBulkCopy(connection, SqlBulkCopyOptions.TableLock, null); 
bulkTask.DestinationTableName = "newTable"; 
bulkTask.BatchSize = dataTable.Rows.Count; 
bulkTask.WriteToServer(dataTable); 
bulkTask.Close(); 

Tôi đã sử dụng SqlBulkCopy trong một nỗ lực để tăng tốc , nhưng nó xuất hiện gán giá trị cho chính DataTable chứng tỏ là chậm.

Tôi không biết DataTables hoạt động như thế nào nên tôi tự hỏi liệu mình có tạo ra các chi phí không cần thiết hay không bằng cách tạo một mảng có thể tái sử dụng, sau đó gán nó cho DataRow, sau đó thêm DataRow vào DataTable? Hoặc đang sử dụng DataTable không tối ưu ở nơi đầu tiên? Dữ liệu đầu vào đến từ cơ sở dữ liệu.

Tôi không quan tâm nhiều về LOC, chỉ tốc độ. Bất cứ ai có thể đưa ra một số lời khuyên về điều này?

+0

Để thực hiện ví dụ, hãy xem 'SimpleDataReader' [ở đây] (https://groups.google.com/group/microsoft.public.dotnet.languages.csharp/msg/b1d70b504cdee2ad?hl=en) –

Trả lời

13

Đối với một bảng lớn như vậy, bạn thay vì phải sử dụng phương pháp

public void WriteToServer(IDataReader reader) 

.

Điều này có nghĩa là bạn sẽ phải tự triển khai giao diện "giả" IDataReader với mã của mình (nếu bạn không nhận được dữ liệu từ IDataReader hiện có), nhưng theo cách này, bạn sẽ nhận được "phát trực tiếp" từ đầu đến cuối và sẽ tránh được vòng lặp 200 triệu.

+1

Đoán bạn đánh bại tôi với nó :) –

+0

Điều đó có nghĩa là SQLBulkCopy vẫn có thể viết hiệu quả cho cơ sở dữ liệu ** như ** các hàng đang được xây dựng ? Dữ liệu đầu vào đến từ cùng một cơ sở dữ liệu, nhưng đối với mỗi hàng tôi có khả năng tạo 20000 cái mới. –

+0

@ Box9 có, chính xác là –

0

Bạn không nên xây dựng toàn bộ dữ liệu trong bộ nhớ. Sử dụng overload của WrtieToServer, có mảng DataRow. Chỉ cần chia nhỏ dữ liệu của bạn.

+0

Isn' t phương pháp đó vẫn còn xây dựng nó trong bộ nhớ? Và bên cạnh đó, nếu tôi không hết bộ nhớ, không phải là xây dựng nó trong bộ nhớ nhanh nhất? –

+0

nếu bạn chỉ xây dựng 1k hàng cùng một lúc thay vì 200m, việc quản lý bộ nhớ giữ số lượng dữ liệu đó sẽ dễ dàng hơn nhiều. bên cạnh đó, gần như chắc chắn bạn sẽ nhận được trao đổi với 200m hồ sơ giữ trong bộ nhớ tại một thời điểm – gor

4

Thay vì giữ bảng dữ liệu lớn trong bộ nhớ, tôi khuyên bạn nên triển khai IDataReader để phục vụ dữ liệu khi bản sao hàng loạt xuất hiện. Điều này sẽ làm giảm sự cần thiết phải giữ tất cả mọi thứ trong bộ nhớ trả trước, và do đó sẽ phục vụ để cải thiện hiệu suất.

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