2008-09-28 2 views
6

Недавно мне пришлось обработать тяжелые вещи с данными, хранящимися в DataSet. Это было достаточно тяжело, и я в конечном итоге использовал инструмент, помогающий выявить некоторые узкие места в моем коде. Когда я анализировал узкие места, я заметил, что хотя поиск DataSet не был ужасно медленным (они не были узким местом), это было медленнее, чем я ожидал. Я всегда предполагал, что DataSets использовал какую-то реализацию стиля HashTable, которая создавала бы поиск O (1) (или, по крайней мере, то, что я считаю HashTables). Скорость моих поисков выглядела значительно медленнее, чем эта.Скорость поиска строк/столбцов DataSet?

Мне было интересно узнать, знает ли кто-нибудь, кто что-нибудь знает о внедрении класса DataSet .NET, поделиться тем, что они знают.

Если я что-то вроде этого:

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

Как быстро будет время поиска будет для метода Contains(...), и для получения значения для хранения в Object o? Я бы подумал, что это очень быстро, как HashTable (предполагая, что я понимаю, что HashTables верен), но это не похоже на это ...

Я написал этот код из памяти, поэтому некоторые вещи могут быть не синтаксически верный".

ответ

2

Via Reflector шаги для DataRow [ "ColumnName"] являются:

  1. Получить DataColumn из ColumnName. Использует DataColumnCollection строки ["ColumnName"]. Внутри DataColumnCollection хранит свои DataColumns в Hastable. O (1)
  2. Получите индекс строки DataRow. Индекс хранится во внутреннем элементе. O (1)
  3. Получите значение DataColumn в индексе с помощью DataColumn [index]. DataColumn хранит свои данные в члене System.Data.Common.DataStorage (внутренний, абстрактный):

    данные возвратаColumnInstance._storage.Get (recordIndex);

    Образец конкретной реализации - System.Data.Common.StringStorage (внутренний, герметичный). StringStorage (и другие конкретные DataStorages, которые я проверил) сохраняют их значения в массиве. Get (recordIndex) просто захватывает объект в массиве значений в recordIndex. O (1)

В целом вы являетесь O (1), но это не значит, что вызов хеширования и функции во время операции будет без затрат. Это просто означает, что это не будет стоить дороже, поскольку число DataRows или DataColumns увеличивается.

Интересно, что DataStorage использует массив для значений.Не могу себе представить, что это легко восстановить при добавлении или удалении строк.

0

Я предполагаю, что любые поисковые запросы будут O (n), так как я не думаю, что они будут использовать любой тип хеш-таблицы, но на самом деле будут использовать больше массива для поиска строк и столбцов.

+0

Это будет O (n^2), поскольку вы выполняете сравнение строк по каждому элементу. – 2008-09-28 01:05:37

0

На самом деле, я считаю, что имена столбцов хранятся в Hashtable. Должен быть O (1) или постоянный поиск для чувствительных к регистру запросов. Если бы ему пришлось просматривать каждый, то, конечно, это было бы O (n).

3

На самом деле рекомендуется использовать целое число при ссылке на столбец, что может значительно улучшить производительность. Чтобы сохранить управляемость, вы можете объявить постоянное целое число. Таким образом, вместо того, что вы сделали, вы могли бы сделать

const int SomeTable_SomeColumn = 0; 

DataTable dt = new DataTable(); 
if(dt.Columns.Contains(SomeTable_SomeColumn)) 
{ 
    object o = dt.Rows[0][SomeTable_SomeColumn]; 
} 
Смежные вопросы