2008-09-28 28 views
6

Gần đây tôi đã phải làm một số công cụ xử lý rất nặng với dữ liệu được lưu trữ trong một DataSet. Đủ lớn đến mức tôi đã sử dụng một công cụ để giúp xác định một số tắc nghẽn trong mã của tôi. Khi tôi đang phân tích các nút cổ chai, tôi nhận thấy rằng mặc dù việc tra cứu số liệu không quá chậm (chúng không phải là nút cổ chai), nhưng nó chậm hơn tôi mong đợi. Tôi luôn luôn giả định rằng DataSets sử dụng một số loại thực hiện phong cách HashTable mà sẽ làm cho tra cứu O (1) (hoặc ít nhất thats những gì tôi nghĩ HashTables được). Tốc độ tra cứu của tôi dường như chậm hơn đáng kể so với điều này.Tốc độ của DataSet hàng/cột tra cứu?

Tôi đã tự hỏi liệu có ai biết bất kỳ điều gì về việc triển khai lớp DataSet của .NET hay không sẽ chia sẻ những gì họ biết.

Nếu tôi làm điều gì đó như thế này:

DataTable dt = new DataTable(); 
if(dt.Columns.Contains("SomeColumn")) 
{ 
    object o = dt.Rows[0]["SomeColumn"]; 
} 

Nhanh như thế nào sẽ là thời gian tra cứu được cho phương pháp Contains(...), và để lấy giá trị để lưu trữ trong Object o? Tôi đã có thể nghĩ rằng nó rất nhanh như một HashTable (giả sử những gì tôi hiểu về HashTables là chính xác) nhưng nó không có vẻ như ...

Tôi đã viết mã đó từ bộ nhớ để một số thứ có thể không phải là "cú pháp chính xác".

Trả lời

2

Via Reflector các bước để DataRow [ "ColumnName"] là:

  1. Lấy DataColumn từ ColumnName. Sử dụng DataColumnCollection của hàng ["ColumnName"]. Bên trong, DataColumnCollection lưu trữ DataColumn của nó trong một Hastable. O (1)
  2. Lấy chỉ mục hàng của DataRow. Chỉ mục được lưu trữ trong một thành viên nội bộ. O (1)
  3. Lấy giá trị của DataColumn tại chỉ mục bằng cách sử dụng DataColumn [index]. DataColumn lưu trữ dữ liệu của nó trong một thành viên System.Data.Common.DataStorage (nội bộ, trừu tượng):

    trả về dữ liệuColumnInstance._storage.Get (recordIndex);

    Triển khai cụ thể mẫu là System.Data.Common.StringStorage (nội bộ, được đóng dấu). StringStorage (và các DataStorages cụ thể khác mà tôi đã kiểm tra) lưu trữ các giá trị của chúng trong một mảng. Nhận (recordIndex) chỉ cần lấy đối tượng trong mảng giá trị tại recordIndex. O (1)

Vì vậy, tổng thể bạn là O (1) nhưng điều đó không có nghĩa là băm và gọi hàm trong quá trình hoạt động không mất phí. Nó chỉ có nghĩa là nó không chi phí nhiều hơn khi số lượng DataRows hoặc DataColumns tăng lên.

Thú vị là DataStorage sử dụng một mảng cho các giá trị.Không thể tưởng tượng dễ dàng để xây dựng lại khi bạn thêm hoặc xóa các hàng.

0

Tôi tưởng tượng rằng mọi tra cứu sẽ là O (n), vì tôi không nghĩ rằng chúng sẽ sử dụng bất kỳ loại hashtable nào, nhưng thực sự sẽ sử dụng nhiều mảng để tìm hàng và cột.

+0

Đó sẽ là O (n^2) vì bạn đang so sánh chuỗi trên từng mục. –

0

Thực ra, tôi tin rằng các tên cột được lưu trữ trong Hashtable. Nên là O (1) hoặc tra cứu liên tục để tra cứu phân biệt chữ hoa chữ thường. Nếu nó phải xem qua từng cái, thì dĩ nhiên nó sẽ là O (n).

3

Thực ra bạn nên sử dụng số nguyên khi tham chiếu cột, có thể cải thiện rất nhiều về hiệu suất. Để giữ cho mọi thứ có thể quản lý được, bạn có thể khai báo số nguyên không đổi. Vì vậy, thay vì những gì bạn đã làm, bạn có thể làm

const int SomeTable_SomeColumn = 0; 

DataTable dt = new DataTable(); 
if(dt.Columns.Contains(SomeTable_SomeColumn)) 
{ 
    object o = dt.Rows[0][SomeTable_SomeColumn]; 
}