2016-08-11 3 views
3

TL; DR версияDataTable.Select против List.FindAll

У меня есть некоторые данные из базы данных либо в DataTable или в виде List<MyData>.

Поскольку я хочу следовать принципам OO, я предпочитаю обрабатывать данные в List<MyData>, но когда дело доходит до производительности, я сталкиваюсь с некоторыми проблемами.

С примерно 150K штук в myDataList.FindAll(x=>x.Id == someId) занимает около 15 миллисекунд, в то время как на другой стороне myDataTable.Select($"ID == {someId}") завершается без StopWatch возможность синхронизации одной миллисекунды.

Поскольку мне нужно выполнить много тысяч поисков по моим данным, 15 миллисекунд на поиск скоро добавляются.

Есть ли другой тип списка, который я могу использовать вместо того, чтобы возвращаться к DataRow[], который возвращает DataTable.Select()? Или я пропустил что-то еще здесь?

Подробная версия

У меня есть приложение, которое считывает данные из двух различных таблиц в базе данных, и нужно, чтобы вычислить что-то по этим данным.

Следуя принципам OO, я получил два списка объектов: List<MyClass> myClassList и List<MyOtherClass> myOtherClassList.

Поскольку факт связи между данными в двух таблицах (через столбец идентификаторов), я хочу переместить их в другой класс, который объединяет их в бизнес-объект: List<MyBusinessObject> myBusinessObjectList.

Так что я сделал следующее:

foreach (var id in myIdList) 
{ 
    var myTmpClassList = myClassList.FindAll(x => x.Id == id); 
    var myTmpOtherClassList = myOtherClassList.FindAll(x => x.Id == id); 

    myBusinessObjectList.Add(new MyBusinessObject(myTmpClassList, myTmpOtherClassList); 
} 

С примерно 35k записей в одном и 160K записей в другой таблице этот процесс занимает около 15 миллисекунд на итерации и вскоре складывает.

С другой стороны

var dic1 = new Dictionary<string, DataRow[]>; 
var dic2 = new Dictionary<string, DataRow[]>; 
foreach (var id in myIdList) 
{ 
    dic1.Add(id, myDataTable.Select($"ID == {id}"); 
    dic2.Add(id, myOtherDataTable.Select($"ID == {id}"); 
} 

завершается в кратчайшие сроки.

Но так как я предпочитаю обрабатывать Objects более Dictionary<string, DataRow[]>, я задаюсь вопросом, есть ли другой подход, который я могу принять.

+0

Пробовали ли вы тот же тест на имуществе, кроме ID?Поскольку я подозреваю, что идентификатор установлен как UniqueKey в DataTable, таким образом, имеет индекс, и, разумеется, двоичный поиск намного быстрее, чем линейный. –

+0

Я не пробовал это с другим свойством, но 'DataTable' не имеет UniqueKey, поэтому я не ожидаю никакой разницы. – sebingel

ответ

2

Здесь

foreach (var id in myIdList) 
{ 
    var myTmpClassList = myClassList.FindAll(x => x.Id == id); 
    var myTmpOtherClassList = myOtherClassList.FindAll(x => x.Id == id); 

    myBusinessObjectList.Add(new MyBusinessObject(myTmpClassList, myTmpOtherClassList); 
} 

выполнения 2 линейных поисковые запросы на каждый идентификатор, что приводит к O(K * (N + M)) временной сложности (где K = myIdList.Count, N = myClassList.Count, M = myOtherClassList.Count).

Вы можете использовать LINQ group joins для соотнесения данных, которые используют довольно эффективный хэш на основе реализации, что приводит к линейной операции временной сложности:

var myBusinessObjectList = 
    (from id in myIdList 
    join x in myClassList on id equals x.Id into myClassGroup 
    join y in myOtherClassList on id equals y.Id into myOtherClassGroup 
    select new MyBusinessObject(myClassGroup.ToList(), myOtherClassGroup.ToList()) 
    .ToList(); 
+1

Работает как очарование. Большое спасибо. Я должен узнать больше LINQ! – sebingel

Смежные вопросы