Clever-Excel-Forum

Normale Version: [Excel] Performance-Test verschiedener VERGLEICHe
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Ich habe eben eine kleine Performance-Messroutine geschrieben.

In dieser sind A:B durchgehende Zufallsdaten der Form A: [A-Z][A-Z][A-D] und B: [A-Z][A-Z] (also über 1048576 bzw. 65536 Zeilen).

Für D:E (entsprechend A:B) kann man in der Routine mit n eingeben, wie viele VERGLEICH-Formeln gerechnet werden sollen. n=30 bedeutet also 30 gleiche Formeln, die sich jeweils über knapp 2,1 Mio (=2^21) Daten her machen.

Verglichen werden {SUMME}, VERGLEICH, {VERGLEICH}, AGGREGAT, SUMMENPRODUKT und SUMMEWENNS.

1. Manchmal wird unterschieden, ob (A:A=D1)*(B:B=E1) oder (A:A&B:B=D1&E1) als Kriterium gerechnet wird. Überraschende Ergebnisse!

2. Bei VERGLEICH wird innen mit INDEX(A:A&B&B;) gerechnet. Auch hier eine Überraschung, die sich etwa hälftig auf den Effekt zu 1. sowie die Verwendung von INDEX statt {} aufteilt.

Ergebnisse:
1. AGGREGAT ist VERGLEICH soweit ebenbürtig (neopa hat recht)
2. {} scheint gegenüber ...INDEX(;)... im Vorteil zu sein (WF hat recht)

Es kommt aber erheblich auf den Einzelfall an. Auch kommt es ein wenig drauf an, ob das Arbeitsblatt frisch ist, oder das Makro schon mehrmals gelaufen ist (wie hier. Dann langsamer).

Anmerkung: Gibt es mehr als ein Auftreten, zeigen VERGLEICH und AGGREGAT das erste, VERWEIS das letzte und die Summenfunktionen deren Addition. Das muss dem Anwender klar sein.

Hier die Einzelergebnisse in Sekunden für n=30 und n=100 (Win10, xl2010, Surface Pro 4, Intel m3, 4 Kerne):

F: 023,87:  =VERGLEICH(D1&E1;INDEX(A:A&B:B;);)
G: 006,82: {=VERGLEICH(D1&E1;A:A&B:B;)}
H: 020,00:  =VERWEIS(2;1/(A:A&B:B=D1&E1);ZEILE(A:A))
I: 010,68:  =SUMMENPRODUKT(ZEILE(A:A)*(A:A=D1)*(B:B=E1))
J: 011,14:  =SUMMENPRODUKT(ZEILE(A:A);N(A:A=D1);N(B:B=E1))
K: 008,92: {=SUMME(ZEILE(A:A)*(A:A=D1)*(B:B=E1))}
L: 022,03:  =AGGREGAT(15;6;ZEILE(A:A)/(A:A&B:B=D1&E1);1)
M: 011,16:  =AGGREGAT(15;6;ZEILE(A:A)/(A:A=D1)/(B:B=E1);1)
N: 003,55:  =SUMMEWENNS(C:C;A:A;D1;B:B;E1)
O: 012,55:  =SUMMENPRODUKT(C:C;N(A:A=D1);N(B:B=E1))
P: 025,09:  =SUMMENPRODUKT(C:C;N(A:A&B:B=D1&E1))
Q: 010,84:  =SUMMENPRODUKT(C:C;-(A:A=D1);-(B:B=E1))
R: 011,01:  =SUMMENPRODUKT(C:C;--(A:A=D1);--(B:B=E1))
S: 011,75:  =SUMMENPRODUKT(C:C;1*(A:A=D1);1*(B:B=E1))
T: 012,00:  =SUMMENPRODUKT(C:C;0+(A:A=D1);0+(B:B=E1))
U: 010,99:  =VERWEIS(2;1/(A:A=D1)/(B:B=E1);ZEILE(A:A))

F: 069,23:  =VERGLEICH(D1&E1;INDEX(A:A&B:B;);)
G: 017,79: {=VERGLEICH(D1&E1;A:A&B:B;)}
H: 065,76:  =VERWEIS(2;1/(A:A&B:B=D1&E1);ZEILE(A:A))
I: 033,02:  =SUMMENPRODUKT(ZEILE(A:A)*(A:A=D1)*(B:B=E1))
J: 035,79:  =SUMMENPRODUKT(ZEILE(A:A);N(A:A=D1);N(B:B=E1))
K: 027,73: {=SUMME(ZEILE(A:A)*(A:A=D1)*(B:B=E1))}
L: 073,49:  =AGGREGAT(15;6;ZEILE(A:A)/(A:A&B:B=D1&E1);1)
M: 035,02:  =AGGREGAT(15;6;ZEILE(A:A)/(A:A=D1)/(B:B=E1);1)
N: 011,36:  =SUMMEWENNS(C:C;A:A;D1;B:B;E1)
O: 038,11:  =SUMMENPRODUKT(C:C;N(A:A=D1);N(B:B=E1))
P: 077,49:  =SUMMENPRODUKT(C:C;N(A:A&B:B=D1&E1))
Q: 034,25:  =SUMMENPRODUKT(C:C;-(A:A=D1);-(B:B=E1))
R: 034,03:  =SUMMENPRODUKT(C:C;--(A:A=D1);--(B:B=E1))
S: 036,75:  =SUMMENPRODUKT(C:C;1*(A:A=D1);1*(B:B=E1))
T: 036,54:  =SUMMENPRODUKT(C:C;0+(A:A=D1);0+(B:B=E1))
U: 034,75:  =VERWEIS(2;1/(A:A=D1)/(B:B=E1);ZEILE(A:A))

Hier noch der Code (mit n = 5, damit es beim Erstdurchlauf nicht zu lange dauert):


Code:
Sub TimerOfLookups()
   [1:1].RowHeight = 13: n = 5: Cells.Clear: Range("F1:U" & n) = "not done yet": [C1] = "1": [C:C].DataSeries
   Range("A:A,D1:D" & n).FormulaR1C1 = "=CHAR(RAND()*26+65)&CHAR(RAND()*26+65)&CHAR(RAND()*4+65)"
   [A:A] = [A:A].Value: Range("D1:D" & n) = Range("D1:D" & n).Value
   Range("B:B,E1:E" & n).FormulaR1C1 = "=CHAR(RAND()*26+65)&CHAR(RAND()*26+65)"
   [B:B] = [B:B].Value: Range("E1:E" & n) = Range("E1:E" & n).Value
   Call Kalk("F", n, False, "=MATCH(RC[-2]&RC[-1],INDEX(C[-5]&C[-4],),)")
   Call Kalk("G", n, True, "=MATCH(RC[-3]&RC[-2],C[-6]&C[-5],)")
   Call Kalk("H", n, False, "=LOOKUP(2,1/(C[-7]&C[-6]=RC[-4]&RC[-3]),ROW(C[-7]))")
   Call Kalk("I", n, False, "=SUMPRODUCT(ROW(C[-8])*(C[-8]=RC[-5])*(C[-7]=RC[-4]))")
   Call Kalk("J", n, False, "=SUMPRODUCT(ROW(C[-9]),N(C[-9]=RC[-6]),N(C[-8]=RC[-5]))")
   Call Kalk("K", n, True, "=SUM(ROW(C[-10])*(C[-10]=RC[-7])*(C[-9]=RC[-6]))")
   Call Kalk("L", n, False, "=AGGREGATE(15,6,ROW(C[-11])/(C[-11]&C[-10]=RC[-8]&RC[-7]),1)")
   Call Kalk("M", n, False, "=AGGREGATE(15,6,ROW(C[-12])/(C[-12]=RC[-9])/(C[-11]=RC[-8]),1)")
   Call Kalk("N", n, False, "=SUMIFS(C[-11],C[-13],RC[-10],C[-12],RC[-9])")
   Call Kalk("O", n, False, "=SUMPRODUCT(C[-12],N(C[-14]=RC[-11]),N(C[-13]=RC[-10]))")
   Call Kalk("P", n, False, "=SUMPRODUCT(C[-13],N(C[-15]&C[-14]=RC[-12]&RC[-11]))")
   Call Kalk("Q", n, False, "=SUMPRODUCT(C[-14],-(C[-16]=RC[-13]),-(C[-15]=RC[-12]))")
   Call Kalk("R", n, False, "=SUMPRODUCT(C[-15],--(C[-17]=RC[-14]),--(C[-16]=RC[-13]))")
   Call Kalk("S", n, False, "=SUMPRODUCT(C[-16],1*(C[-18]=RC[-15]),1*(C[-17]=RC[-14]))")
   Call Kalk("T", n, False, "=SUMPRODUCT(C[-17],0+(C[-19]=RC[-16]),0+(C[-18]=RC[-15]))")
   Call Kalk("U", n, False, "=LOOKUP(2,1/(C[-20]=RC[-17])/(C[-19]=RC[-16]),ROW(C[-20]))")
   MsgBox [DA1]
End Sub

Sub Kalk(Spalte, n, Arr As Boolean, Formel): a = Timer
  If Arr Then
     Range(Spalte & "1").FormulaArray = Formel: Range(Spalte & "1:" & Spalte & n).FillDown
  Else
     Range(Spalte & "1:" & Spalte & n).FormulaR1C1 = Formel
  End If: b = Timer - a
  Formel = Range(Spalte & "1").FormulaLocal
  Range(Spalte & "1:" & Spalte & n) = Range(Spalte & "1:" & Spalte & n).Value
  Range("A" & Spalte & "1") = b
  Range("B" & Spalte & "1").FormulaR1C1 = "=TEXT(RC[-26],""000,00"")"
  Range("C" & Spalte & "1") = IIf(Arr, "{", " ") & Formel & IIf(Arr, "}", " ")
  [DA1] = [DA1] & Chr(10) & Spalte & ": " & Range("B" & Spalte & "1") & ": " & Range("C" & Spalte & "1")
End Sub