Überraschende Leistungsunterschiede: List.Constains, SortedList.ContainsKey, DataRowCollection.Contains, DataTable.Select, DataTable.FindBy

Ursprünglich wollte ich nach dem schnellsten Weg fragen, eine Datentabelle für eine bestimmte Zeile abzufragen.

Ich habe 5 verschiedene Methoden auf ihre Leistung getestet und ein (für mich) überraschendes Ergebnis erzielt.

Background: Ich habe eine Ansicht in einer MS SQL-Server 2005-Datenbank erstellt. In dieser Ansicht werden derzeit insgesamt 6318 Zeilen gezählt. Da ich in dieser Ansicht sehr oft prüfen muss, ob eine bestimmte ID vorhanden ist, habe ich mich gefragt, wie das am effizientesten funktioniert. Ich habe einen DataAdapter in einem stark typisierten Dataset erstellt, der alle Zeilen zurückgibt und eine Datentabelle ausfüllt. Mein erster Ansatz bestand darin, eine gemeinsame generische Liste (von Int32) zu erstellen und diese beim Anwendungsstart mit den IDs aus der Ansicht zu füllen. Dann benutze List.Contains, um zu überprüfen, ob die aktuelle ID in dieser Liste enthalten ist. Da alle Zeilen unterschiedlich sind, habe ich mich gefragt, ob es nicht schneller ist, eine SortedList und das @ zu verwende EnthältKey -metod. Dann überprüfte ich auch die Leistung des direkten Zugangs zum Datable mit seinem Select-Methode, wird automatisch generiert (wenn die Spalte als Primärschlüssel definiert ist) FindBy-Methode und nicht zuletzt das DatarowCollection.Contains-Methode. Ich habe also 5 Methoden, um zu überprüfen, ob sich meine ID in dieser Ansicht (oder in der zugeordneten Liste / SortedList) befindet.

Ich habe ihre Leistung mit dem @ gemess System.Diagnostics.StopWatch und habe einige interessante Ergebnisse. Ich dachte, der SortedList.ContainsKey muss schneller sein als der List.Contains, weil sie unterschiedlich und sortiert sind, aber das Gegenteil ist der Fall. Das Überraschendste für mich war jedoch, dass die DataRowCollection.Contains-Methode (die ich zum ersten Mal vergessen hatte) bei weitem die schnellste ist. Es ist sogar 50-mal schneller als die dataTable.FindBy-Methode.

Was hat diese Unterschiede verursacht?Habe ich einen besseren Weg vergessen?Ist meine Messmethode korrekt (ich denke, ich sollte sie besser schleifen und diese Werte nehmen)? Sind die Werte übertragbar oder abhängig von der Größe der Daten / Sammlung?Nach meinem Update (1000000 Iterationen) ist ContainsKey am schnellsten. Liegt das daran, dass ich immer nach der gleichen ID suche oder im Allgemeinen? Gibt es eine Art SortedList ohne den Overhead des KeyValue-Paars eines Dictionary?

Ergebniss [für 1000000 Iterationen *]

Timespan 1 = SortedList.ContainsKey = Ø 0,65634 238.1095] FraTimespan 2 = List.Contains = Ø 0,06802 57045.37955] FraTimespan 3 = DataTable.FindByIdData (automatisch generierte Methode) = Ø 0,31580 1542.62345] FraTimespan 4 = DataTable.Select = Ø 0,27790 26029.39635] Fra

Timespan 5 = DataRowCollection.Contains = Ø 0,00638 1202.79735] Fra

1.)
Timespan 1: 0,6913 ms
Timespan 2: 0,1053 ms
Timespan 3: 0,3279 ms
Timespan 4: 0,1002 ms
Timespan 5: 0,0056 ms

2.)
Timespan 1: 0,6405 ms
Timespan 2: 0,0588 ms
Timespan 3: 0,3112 ms
Timespan 4: 0,3872 ms
Timespan 5: 0,0067 ms

3.)
Timespan 1: 0,6502 ms
Timespan 2: 0,0588 ms
Timespan 3: 0,3092 ms
Timespan 4: 0,1268 ms
Timespan 5: 0,007 ms

4.)
Timespan 1: 0,6504 ms
Timespan 2: 0,0586 ms
Timespan 3: 0,3092 ms
Timespan 4: 0,3893 ms
Timespan 5: 0,0063 ms

5.)
Timespan 1: 0,6493 ms
Timespan 2: 0,0586 ms
Timespan 3: 0,3215 ms
Timespan 4: 0,386 ms
Timespan 5: 0,0063 ms



Timespan 1: 0,6913 0,6405 0,6502 0,6504 0,6493 = Ø 0,65634
Timespan 2: 0,1053 0,0588 0,0588 0,0586 0,0586 = Ø 0,06802
Timespan 3: 0,3279 0,3112 0,3092 0,3092 0,3215 = Ø 0,31580
Timespan 4: 0,1002 0,3872 0,1268 0,3893 0,3860 = Ø 0,27790
Timespan 5: 0,0056 0,0067 0,0070 0,0063 0,0063 = Ø 0,00638

nd der Vollständigkeit halber Teil des VB.Net source:

Dim applies As Boolean
Dim clock As New System.Diagnostics.Stopwatch

clock.Start()
For i As Int32 = 1 To 1000000
    applies = sortedListAC17NextClaims.ContainsKey(myClaim.idData)
Next
clock.Stop()
Dim timeSpan1 As String = "Timespan 1: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = listAC17NextClaims.Contains(myClaim.idData)
Next
clock.Stop()
Dim timeSpan2 As String = "Timespan 2: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = Not MyDS.AC17NextClaims.FindByIdData(myClaim.idData) Is Nothing
Next
clock.Stop()
Dim timeSpan3 As String = "Timespan 3: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = MyDS.AC17NextClaims.Select("idData=" & myClaim.idData).Length > 0
Next
clock.Stop()
Dim timeSpan4 As String = "Timespan 4: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = MyDS.AC17NextClaims.Rows.Contains(myClaim.idData)
Next
clock.Stop()
Dim timeSpan5 As String = "Timespan 5: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

AKTUALISIEREN Ich habe meine Ergebnisse und die Quelle oben geändert. In eckigen Klammern sind die Werte für 1000000 Iterationen angegeben. Jetzt ist das Ergebnis völlig anders. Die schnellste Methode ist jetzt definitiv der ContainsKey der SortedList.

UPDATE 2: Ich habe die Alternative zu @ vergess List.BinarySearch. Das scheint für mich am schnellsten zu sein:

clock.Start()
For i As Int32 = 1 To 1000000
    applies = listAC17NextClaims.BinarySearch(myClaim.idData) > -1
Next
clock.Stop()

braucht nur 219.1805 ms, um 1000000 Iterationen durchzuführen, und ist daher die schnellste ohne den Overhead eines SortedList-KeyValue-Pair. Ich kann es verwenden, ohne die Liste zu sortieren, da der DataAdapter die Datentabelle mit einer Order By-Klausel gefüllt hat.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage