2009-03-09 12 views
19

Mam DataTable/kolekcja, która jest buforowana w pamięci, chcę użyć tego jako źródło do generowania wyników dla automatycznego uzupełniania pola tekstowego (oczywiście przy użyciu AJAX). Oceniam różne opcje szybkiego pobierania danych. Liczba pozycji w kolekcji/wierszach w datatable może się różnić od 10000 do 2 000 000. (Abyśmy nie zostali przekierowani, na razie zakładamy, że decyzja została podjęta, mam wystarczającą ilość pamięci RAM i będę używać pamięci podręcznej, a nie zapytania do bazy danych)DataTable.Select vs DataTable.rows.Find vs foreach vs Find (Predicate <T>)/Lambda

Mam dodatkową logikę biznesową dla tego przetwarzania ; Muszę nadać priorytet liście autouzupełniania zgodnie z kolumną priority (int) w kolekcji. Więc jeśli ktoś szuka Micro i otrzymuję 20 wyników słów/zdań, które zaczynają się od Micro, wtedy wybrałbym 10 najbardziej wypadkowych przedmiotów o najwyższym priorytecie. (stąd potrzeba posiadania właściwości priorytetowej związanej z wartością ciągu znaków).

Elementy kolekcji są już posortowane alfabetycznie.

Jakie byłoby najlepsze rozwiązanie w tym przypadku.
1. Za DataTable.Select (.
2. Using DataTable.Rows.Find(.
3. Zastosowanie zwyczaj Odbiór foreach or for iterację jego wartości.
4. Zastosowanie ogólny zbiór z anonymous delegates lub lambda (since both give same performance lub not?)

Odpowiedz

2

Możemy spekulować o tym cały dzień, ale ponieważ nie jest to ogromny kawałek kodu, to dlaczego nie napisać każdy i odniesienia ich przed sobą?

public delegate void TestProcedure(); 

public TimeSpan Benchmark(TestProcedure tp) 
{ 
    int testBatchSize = 5; 
    List<TimeSpan> results = new List<TimeSpan>(); 
    for(int i = 0; i<testBatchSize; i++) 
    { 
     DateTime start = DateTime.Now; 
     tp(); 
     results.Add(DateTime.Now - start); 
    } 
    return results.Min(); 
} 
+0

Sprawdzam tylko, czy ktoś już "tam był". –

+0

Jeśli wykonasz test porównawczy, daj nam znać! Jestem ciekaw, co znajdziesz. –

0

co z Da taView? Możesz zastosować warunek filtru i sortować według priorytetu, a następnie łatwo iterować wyniki, aby dodać wyniki.

+0

Tak, opcja 2 w pytaniu robi dokładnie to. –

4

Na moim autocomplete próbowałem najpierw podejście linq/lambda, wydajność jest trochę powolna. DataTable.Select jest szybszy niż linq, więc używam tego. Jeszcze nie porównał wydajność między datatable.Select i datatable.Find

+0

Czy masz indeks na kluczu filtrowania? –

+0

Pytanie tego plakatu dotyczy filtrowania DataTable. Dlatego indeks bazy danych nie może być tutaj zastosowany. DataTable ma wewnętrzny indeks w pamięci dla wierszy i jest dostępny tylko przez DataTable.Select (przypuszczam, że DataTable.Find może również uzyskać dostęp do tego wewnętrznego indeksu). Linq-to-object nie może uzyskać dostępu do tego wewnętrznego indeksu, ponieważ pod Linkiem-do-obiektu pętle zawierają wszystkie elementy. Chyba, że ​​ktoś stworzy Linq-to-DataTable dostawca, który używa DataTable.Select wewnętrznie, filtrowanie DataRow z DataTable za pomocą Linq/Lambda nadal będzie rozczarowujące. DataTable architecture http://j.mp/k56g37 –

+0

Moje pytanie dotyczyło wewnętrznego indeksu DataTable. Również według http://msdn.microsoft.com/en-us/library/dd364983.aspx "indeksowanie tabeli zapewnia niewielką przewagę w zapytaniu LINQ" –

8

Wykresy nie są publikowane na moim blogu; Więcej szczegółów można znaleźć pod adresem: http://msdn.microsoft.com/en-us/library/dd364983.aspx

Kolejną rzeczą, którą odkryłem, jest to, że w przypadku dużych zestawów danych używanie połączonego słownika generycznego działa niewiarygodnie dobrze. Pomaga także zmniejszyć wiele problemów spowodowanych operacjami sortowania wymaganymi do operacji agregacji, takich jak min. I maks. (Z DataTable.Compute lub LINQ).

Przez "połączony słownik ogólny" mam na myśli Dictionary(Of String, Dictionary(Of String, Dictionary(Of Integer, List(Of DataRow)))) lub podobną technikę, w której kluczem do każdego słownika jest wyszukiwany termin.

To prawda, nie przyda się we wszystkich okolicznościach, ale mam co najmniej jeden scenariusz, w którym wdrożenie tego podejścia prowadzi do poprawy wydajności 500x.

W twoim przypadku rozważam użycie prostego słownika z pierwszymi 1-5 znakami, a następnie List(Of String). Trzeba by raz zbudować ten słownik, dodając słowa do list z pierwszymi 1-5 znakami, ale potem uzyskasz niesamowicie szybkie wyniki.

Zazwyczaj zawijam takie rzeczy w klasie, która pozwala mi na łatwe dodawanie słów. Możesz również użyć opcji SortedList(Of String), aby automatycznie posortować wyniki. W ten sposób możesz szybko wyszukać listę słów pasujących do pierwszych N znaków, które zostały wpisane.

+0

I jesteś całkiem "Pewny" o tym! –