SharePointCommunity
Die deutschsprachige Community für SharePoint, Microsoft 365, Teams, Yammer und mit Azure

Sponsored by

Willkommen im Forum Archiv.
Einträge sind hier nicht mehr möglich, aber der Bestand von 12 Jahren SharePoint-Wissen ist hier recherchierbar.




Geschwindigkeit von "foreach (SPListItem item in aList.Items)"

Unbeantwortet Dieser Beitrag hat 27 Antworten

Ohne Rang
255 Beiträge
stephan12345 erstellt 10 Okt. 2011 14:21
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo zusammen,

weiß jemand wie die Iteration über

foreach (SPListItem item in aList.Items)

intern funktioniert. Ist es schneller einen CAML Query zu schreiben und dann über alle Elemente zu iterien ?

Gruß
Stephan

Alle Antworten

Ohne Rang
19231 Beiträge
Andi Fandrich Als Antwort am 10 Okt. 2011 14:44
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Das hängt letztlich davon ab, was Du vorhast. Wenn Du eh nur ein Subset brauchst, ist die CAML-Query sicher besser. Wenn die Anzahl der Elemente das eingestellte Limit überschreiten kann, dann liefert Dir der Zugriff auf SPList.Items einen Fehler, aber die CAML-Query geht trotzdem. Ansonsten erzeugt SPList.Items intern auch nur eine leere Query...

Nur zur Info (und nicht nur für Dich):

Jeder Zugriff auf SPList.Items lädt alle Elemente aus der Datenbank. Sowas sollte man also nicht machen:
for (int i=0; i < myList.Items.Count; i++) {
 SPListItem item = myList.Items[i];
}

Viele Grüße
Andi
af @ evocom de
Blog
Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 10 Okt. 2011 14:58
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo zusammen,

in meinem Fall brauche ich alle Elemente.
Ich will alle Elemente aus einer Liste (ca.300) in eine DropDownListe in einem WebPart schreiben. Dabei soll der Title in der DropDown erscheinen.
Das ist aber sehr langsam mit dem Iterator über aList.Items.

Gruss

Stephan

 

Ohne Rang
235 Beiträge
FCaprio Als Antwort am 10 Okt. 2011 15:50
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hmm. Also die Abfrage mit CAMl machen, deine Items in eine "List" übertragen und diese dann an die DropDown Box binden. sollte eigentlich sehr fix sein.

Aber mal Ehrlich 300 Items in einer Dropdownbox sind für den User doch nicht wirklich zu handhaben.

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 10 Okt. 2011 15:54
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hi,

ich habe jetzt mal verschiedene Medthoden getestet.
Ob CAML und direkt über foreach(SPItelm item in aList.Items)
ist gleich langsam.
Die Filter werden nachher auf Frontend-Seite über JavaScript gesetzt, 300 wären wirklich etwas viel ;-)

Gruß
Stephan

Ohne Rang
19231 Beiträge
Andi Fandrich Als Antwort am 10 Okt. 2011 15:58
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

[quote user="stephan12345"]Ob CAML und direkt über foreach(SPItelm item in aList.Items) ist gleich langsam[/quote]

Wie oben geschrieben: SPList.Items erzeugt auch nur eine leere SPQuery...

300 Items sollten allerdings nicht wirklich ein Problem darstellen (außer bei der Auswahl durch den User). Ich denke, daß da eher Deine Weiterverarbeitung zu langsam ist ;-)

[quote user="stephan12345"]Die Filter werden nachher auf Frontend-Seite über JavaScript gesetzt[/quote]

Kannst Du das nicht serverseitig umbauen?

Viele Grüße
Andi
af @ evocom de
Blog
Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 10 Okt. 2011 16:07
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hi Andi,

ja serverseitig war die Anwendung vorher, der Roundtrip ist dabei leider zu langsam. ich schreibe gerade cascadierende Lookups.

Wenn ich die foreach in meinen Code einbaue und lasse dabei keine DropDownListe füllen, dann geht die Geschwindigkeit auch
rapide nach unten. Fülle ich die DropDonwListen mit Zahlen (1-300 z.B aus einer For schleife) dann das richtig schnell.

Daher bin ich eher auf der Suche nach einem foreach Ersatz / Lösung.

Gruß
Stephan 

Ohne Rang
19231 Beiträge
Andi Fandrich Als Antwort am 10 Okt. 2011 16:24
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Da habe ich dann leider auch keine Idee mehr. Aber Du bist schon sicher, daß Du nicht mehrmals auf SPList.Items zugreifst?

Viele Grüße
Andi
af @ evocom de
Blog
Ohne Rang
634 Beiträge
Olaf Didszun Als Antwort am 10 Okt. 2011 19:57
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hast Du schon mal versucht, statt über das "normale" API über die Web Services Deine Items zu lesen? Da ja das Webpart auf dem Server selbst läuft, scheint das auf den ersten Blick keinen Sinn zu machen, aber zumindest beim Löschen von sehr vielen Elementen in einer Liste habe ich die Erfahrung gemacht, dass diese Operation über die Web Services von SharePoint deutlich schneller läuft.

Schau Dir ggf. mal Lists.GetItems() an. Liefert Dir vermutlich schon mit einem Aufruf alle Elemente, die Du haben willst, sodass Du nur noch durch den XMLNode laufen musst.

Grüße

Olaf

 

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 11 Okt. 2011 13:43
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo Olaf,

list.GetItems() habe ich mal probiert bringt aber auch keinen großen Geschwindigkeitsvorteil.

Danke und Gruß

Stephan

Ohne Rang
235 Beiträge
FCaprio Als Antwort am 12 Okt. 2011 08:17
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Kannst du mal den ganzen Code posten in dem du die Abfrage machst?

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 09:04
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

klar,

 foreach (SPListItem item in list.Items) {


     ListItem dropDownItem = new ListItem(item["Title"].ToString());

     dropDownItem.Value = item.ID.ToString() + ";" + item[metaDataControl.control_parent_id].ToString();
                   
     dropDownList.Items.Add(dropDownItem);
 }

 

Wobei ich diese Methode für vier DropDownListen aufrufe.
Macht es evlt. Sinn die vier Listen in einer CAML Query zu Joinen und dann  beim Füllen der DropDownlisten
zu entscheiden, wo jeder Datensatz hinein soll ?

 

 

Gruß
Stephan

Ohne Rang
235 Beiträge
FCaprio Als Antwort am 12 Okt. 2011 09:40
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

CAML ist normalerweise immer schneller. Also dieses List.Items durch CAML austauschen das ist das einzige was ich da als Beschleunigung sehen würde.

Ohne Rang
634 Beiträge
Olaf Didszun Als Antwort am 12 Okt. 2011 11:11
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo Stephan,

schau Dir noch mal die erste Antwort von Andy an.

Versuche es mal damit:

SPListItemCollection items = list.Items;

foreach (SPListItem item in items) {


ListItem dropDownItem = new ListItem(item["Title"].ToString());

dropDownItem.Value = item.ID.ToString() + ";" + item[metaDataControl.control_parent_id].ToString();

dropDownList.Items.Add(dropDownItem);
}

Grüße

Olaf

 

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 11:33
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hallo Olaf,

kein Unterschied mit

SPListItemCollection items = list.Items;

foreach (SPListItem item in items) {

 

 

 Ich probiere es gleich mal über ein CAML Query.

Gruß

Stephan

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 11:49
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Also über SPQuery macht es auch nicht schneller.

Ich hab sogar mal proviert , die Felder die ich brauche über  query.ViewFields einzugrensen.
Brachte aber auch keinen Erfolg. Dann scheint der SharePoint einfach so langsam zu sein.

GRuß

Stephan

Ohne Rang
235 Beiträge
FCaprio Als Antwort am 12 Okt. 2011 11:55
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Kannst du einen Zeitstempel vor dem Auslesen und direkt nach dem CAML und dann noch nach der foreach posten?

Wenn das CAML langsam ist liegt es am Server (Bei deiner beschriebenen Datenmenge sollte das fix sein). Aber ich würde das nicht auf Sharepoint direkt schieben. Wie ist deine Hardware? Vielleicht liegt da der Flaschenhals.

 

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 12 Okt. 2011 11:58
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hi,

hast Du Andis Vorschlag bzgl. einer for-Schleife und nicht foreach berücksichtig?

wenn es extrem unperformant ist, könnte man auch noch EventHandler an die Liste hängen, welche bei sämtliche Änderungen (Anlegen, Ändern, Löschen) anspringen und den geforderten Wert in die Web-Properties schreiben z.B. per HashSet.

Dann könnte das Webpart bei Zugriff daraus befüllt werden - bringt vielleicht Geschwindigkeitsvorteile ist aber auch ein gewisse Entwicklungsoverhead.

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 13:17
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hi,

ja das ist klar, so sollte man es NICHT machen:

Jeder Zugriff auf SPList.Items lädt alle Elemente aus der Datenbank. Sowas sollte man also nicht machen:
for (int i=0; i < myList.Items.Count; i++) {
 SPListItem item = myList.Items[i];
}

Ich denke mit meiner foreach Lösung habe ich schon alles ausgereitzt.
Die Idee mit dem PropertiyBack ist gar nicht schlecht.

Ist halt die Frage, ob das soviel schneller ist ?

Grüße

Stephan

 

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 12 Okt. 2011 14:10
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Ajo wir werden uns hier auch in Geschwindikeitsbereichen bewegen, die dem Nutzer eh kaum auffallen sollten (foreach im Vergleich zu for), trotzdem sollte die for-Schleife noch ein paar Geschwindigkeitsvorteile bieten (zumindest als ich es gerade mit verschiedenen Array-Typen in einer Konsolenanwendung getestet habe, bewegt sich der Voteil fast immer um den Faktor 2).

Ich würde aber mal messen, wo genau der Flaschenhals liegt (eventuell mit StopWatch) damit Du nicht an etwas rumoptimierst, was eigentlich kaum ins Gewicht fällt.

Wie lange dauert es denn bis deine DropDown-Liste gefüllt bzw. das Webpart benutzbar ist?

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 14:31
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Habe jetzt auch ein wenig mit der for schleife experimentiert und dabei einen interessanten link gefunden:

http://blog.dynatrace.com/2009/01/11/the-wrong-way-to-iterate-through-sharepoint-splist-items/

bringt aber auch keinen großen Geschwindigkeitesvorteil gegebenüber der foreach.

 

Ohne Rang
235 Beiträge
FCaprio Als Antwort am 12 Okt. 2011 14:34
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Ohne Geschwindigkeitsmessung und nur auf "geühltem" beruhend kann man sowas nicht messen. Bitte Zeiten messen.

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 14:41
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hab jetzt mal die Zeit gemessen

Liste       Items      t-for           t-foreach

L1            41          261 ms     282 ms
L2          226        1451 ms    1624 ms
L3          524        3265 ms     3639 ms

Also ihr seht, die for schleife ist etwas schneller, aber für meine Anwender sind die ca. 6 Sekunden definitiv zu viel.

Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 12 Okt. 2011 14:53
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Hm ok für 500 Elemente erscheint mir dies auch etwas lange - die Zeiten sind nur für das Befüllen der DropDown-Liste genommen worden oder für den gesamten Prozess?

Ohne das jetzt weiter genau testen zu können - bringt das hier eventuell was:

DropDownList.Items.Add(item.ID.ToString() + ";" + item[metaDataControl.control_parent_id].ToString());

Also die Werte für die DropDownListe ohne das "ListItem" befüllen?

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de

Ohne Rang
235 Beiträge
FCaprio Als Antwort am 12 Okt. 2011 15:04
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Wie schnell ist es wenn du nur so

DropDownList.Items.Add(item.ID.ToString() );

befüllst?

 

Ohne Rang
255 Beiträge
stephan12345 Als Antwort am 12 Okt. 2011 15:10
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

So ich habe die Ursache für die Verzögerung gefunden.

Wundert mich dass Andi nicht gleich draufkam ;-)

Meine Application läuft als sandboxed solution.
Ich habe jetzt die gleiche Schleife in eine Farmsolution gepackt  und nochmal gemessen, da komme ich
auf 88ms bei L3. In der Sandboxed waren es 3,5 Sekunden.

Hätte ich nicht gedacht, dass das so viel ausmacht.

Grüeß
Stephan

Ohne Rang
19231 Beiträge
Andi Fandrich Als Antwort am 13 Okt. 2011 11:13
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

[quote user="stephan12345"]Wundert mich dass Andi nicht gleich draufkam ;-)[/quote]

Ich hätte auch nicht gedacht, daß die Sandbox das dermaßen ausbremst. Zum Glück sind meine Kunden da vernünftiger und lassen mich Farm Solutions bauen. Das solltest Du auch mal durchsetzen ;-)

Viele Grüße
Andi
af @ evocom de
Blog
Ohne Rang
1714 Beiträge
C.Kaiser Als Antwort am 10 Okt. 2011 14:45
SchlechtSchlechtIn OrdnungIn OrdnungDurchschnittDurchschnittGutGutSehr gutSehr gut

Moin,

die CAML-Query wird ja i.d.R. dazu genutzt um bestimmte Werte zu filtern und die entsprechend gefilterte ItemCollection zurückzubekommen. Da sollte CAML deutlich schneller sein, als wenn Du manuell per foreach filterst (vor allem auch deutlich einfacher zu warten).

So wie ich Deine Frage aber verstehe willst Du dir erst per CAML alle Elemente einer Liste holen und dann per foreach etwas machen. Da macht CAML keinen Sinn sondern ist einfach ein überflüssiger Schritt.

Beste Grüße,
Christian

http://www.sharepoint-rhein-ruhr.de