Nachhaltige Power Apps durch geschicktes Filtern und Laden von Daten
Dieser Artikel ist Teil meiner Serie über nachhaltige Power Platform Lösungen.
Im Wesentlichen geht es bei nachhaltiger Softwareentwicklung – egal, ob ProCode, LowCode oder NoCode – darum, möglichst wenige Ressourcen zu verbrauchen und gleichzeitig möglichst viele Vorteile des mobilen Arbeitens zu nutzen.
Weniger Netzlast durch weniger Requests
Ein wesentlicher Punkt bei der Reduzierung von CO2-Emissionen ist es, die Netzlast, also den Datenverkehr, zu minimieren.
Wie reduziere ich die Netzlast bei der Entwicklung von Power Apps
Indem ich weniger Requests absetze und weniger Daten transportiere.
Siehe auch: Der HTML-Code für ein Leerzeichen ist folgender: Principle 6: Network efficiency – Learn | Microsoft Docs
Eventuell helfen Euch die folgenden Ideen, Eure App dahingehend zu optimieren.
Idee 1: Frage nur nach den Daten, die Du wirklich benötigst
Der einfachste Weg, externe Datenquellen in Power Apps verfügbar zu machen, ist die Bindung eines Controls, wie z.B. einer Gallery, an den Connector zur Datenquelle. Das ist das Standardverfahren, wenn eine App ausgehend von einer Datenquelle erzeugt wird

Das Ergebnis ist eine hübsche App mit einem für den mobilen Einsatz optimierten Layout.

Als Datenbestand dient uns hier eine recht überschaubare SharePoint-Liste mit gerade einmal neun Einträgen:

Aufgrund des Filters, aus dem die Gallery ihre Daten bezieht, werden zunächst alle Daten geladen und angezeigt.

Jede Eingabe in die Textbox Search items führt zu einer gefilterten Abfrage gegen die Datenquelle. Das kann man hervorragend im Power Apps Monitor nachvollziehen, denn die Filterung nach dem Begriff „Decision to Buy“ führte zu vier Datenabfragen:


Was ist passiert?
Zunächst erfolgt aufgrund der leeren Filterbox eine ungefilterte Abfrage gegen die Datenquelle mit allen Datensätzen, was zu rund 15.000 Byte Response führt.
Da jede Eingabe zu einer Datenabfrage führt, erfolgen bei der Eingabe von drei Buchstaben auch drei Datenabfragen, was zusammen 8.300 Bytes Response ergibt.
DelayOutput
Wie oben gezeigt, habe ich drei Suchvorgänge dadurch ausgelöst, dass nach jeder Zeicheneingabe eine Suche erfolgt. Einschränken lässt sich dies durch die Eigenschaft DelayOutput an der Textbox für den Suchfilter. Diese Eigenschaft bewirkt, dass die Textbox ihr Ergebnis etwas zeitverzögert an den Filter weitergibt.

Das ist dringend zu empfehlen, denn wenn man weiß, was man sucht und intuitiv schnell tippt, lässt sich aus den letzten drei Requests ein einziger machen, was zu einer Datenreduzierung von 8.300 Byte auf etwa 1.700 Byte führt.
Tippt man etwas langsamer, erzeugt man entsprechend viele Abfragen.
Daten nur laden, falls nötig
Es gibt keinen logischen Grund immer alle Daten zur Anzeige zu bringen, denn in der Regel such ich einen bestimmten Datensatz. Ergänze ich den Filter so, dass nur gefiltert wird, wenn tatsächlich eine Eingabe vorliegt, kann ich die transportierten Daten massiv herunterschrauben:


Vordefinierte Filter
Füge ich der Gallery dann noch vordefinierte Filter hinzu, die die häufigsten Abfragen abdecken, so kann ich auf die ungefilterte Abfrage komplett verzichten und spare mir die initialen 15.000 Byte komplett.
Sinnvolle Filter aus meiner Projektpraxis:
- Alle (Mache stöbern halt gerne)
- Meine Datensätze
- Aktive / Deaktive Datensätze
- Neuste Datensätze
- Zuletzt geändert
Achtung! Im Einzelnen ist auf das Problem der Delegation zu achten: https://docs.microsoft.com/de-de/powerapps/maker/canvas-apps/delegation-overview)
Reicht das nicht aus, so lassen sich auch etwas detailliertere Filtermechanismen implementieren, die z.B. die Filterung nach bestimmten Produktgruppen etc. vornehmen.
Idee 2: Erst tippen, dann suchen
Nun kommt mir in den Sinn: Na, dann suche ich doch nicht dynamisch, sondern tippe erst und suche dann. Das hat aber zwei Nachteile:
1. Die App fühlt sich an wie vor 20 Jahren, da ich exakt wissen muss, was ich suche. Das will niemand!
2. Weiß ich nicht exakt, was ich suche, werde ich öfter neue Suchanfragen abfeuern, die jede für sich zwar klein sind, aber zum einen sehr häufig ausgeführt werden, und zum anderen für eine längere Nutzungsdauer der App sorgen. Damit erhöhen sich der Stromverbrauch und der Zeitaufwand für den Nutzer. Auch das will niemand!
Idee 3: Cache Daten
Der einfachste Weg, um Datenabfragen zu reduzieren, wäre dann schlicht keine zu machen. Wie geht das? Indem ich die Daten zu Beginn lade und mir so einen Cache aufbaue.
Wie mache ich das?
Ich stelle die App einfach so um, dass ich die Daten in App.OnStart lade und nur noch auf dem so erzeugten Cache arbeite:

Der Filter sieht dann so aus:

Schaue ich nun auf den Monitor, ergibt sich dieses Bild:

Es werden einmalig ca. 15.000 Bytes geladen und nur noch auf diesem Datenbestand gearbeitet.
Refresh
Nun arbeite ich immer auf einem Datenbestand, der so aktuell ist, wie zu dem Zeitpunkt, als ich die App öffnete. Seht also unbedingt eine Möglichkeit vor, den Datenbestand zu aktualisieren. In unserer App könnte das das Reload-Icon übernehmen, dessen Code ich im OnSelect etwas modifiziere:

vorher

nachher
Und die Lösung?
Es kommt darauf an! Meist arbeite ich mit mehreren Datenbeständen, die ich allesamt vorladen müsste, was durch die sequentielle Abarbeitung der Abfragen zu einem gefühlten Stillstand der App führt.
Nutzt also unbedingt das Concurrent-Konstrukt, um die Datenabfragen zu parallelisieren. Die Ladezeit der App verkürzt sich drastisch:
https://docs.microsoft.com/de-de/powerapps/maker/canvas-apps/functions/function-concurrent
Und eine direkt an die Datenquelle gebundene Gallery? Ist grundsätzlich ein guter Ansatz, denn sie lädt nur die ersten 100 Datensätze, wie der Monitor zeigt:

Erst wenn ich in der Gallery weiter nach unten scrolle, so wird nachgeladen, was zwar wiederum zusätzlichen Traffic verursacht, aber auch nur den des nächsten Datenpakets. Michal Guzowski beschreibt das wunderbar in diesem Blog:
https://michalguzowski.pl/how-to-overcome-500-items-limit-in-powerapps/
Folgt da bitte auch unbedingt den Hinweisen zur Delegation, die ich unter dem Gesichtspunkt des Datentransfers noch einmal gesondert unter die Lupe nehme!
Was würde ich tun?
Ich würde es von der Nutzung abhängig machen. Geht es um eine kurze Session mit wenigen Abfragen, so würde ich
- Filter vordefinieren, um kurze initiale Abfragen zu haben.
- nur delegierbare Abfragen verwenden.
- Ergebnisse direkt an eine Gallery binden, um vom aktiven Nachladen zu profitieren.
- Textboxen, die für Filterabfragen genutzt werden, mit DelayOutpu=true versehen.
Geht es darum, dass die App geöffnet wird und einen über den Tag begleitet, würde ich Folgendes tun:
- verschiedene gefilterte Daten cachen. (Concurrent !)
- eine manuelle und eine zeitgesteuerte Refresh-Möglichkeit vorsehen.
- nur, wenn eine hohe Datenaktualität notwendig ist, direkt gegen die Datenquelle arbeiten.
In jedem Fall empfehle ich regelmäßig die Benutzung der App zu kontrollieren. Möglichkeiten dazu sind vorhanden:
https://powerapps.microsoft.com/en-us/blog/use-monitor-to-debug-your-published-app/
https://docs.microsoft.com/de-de/powerapps/maker/canvas-apps/application-insights
Bringt das denn überhaupt was? Eine kleine Rechnung:
- Jede Ersparnis von unnützem Datentransfer bringt was!
- Falls ihr es nicht für die Umwelt tut, dann für die Performance Eurer App. Die User danken es Euch!
Ich hatte hier eine überschaubare Liste mit neun Einträgen. Diese verursachten 15.000 Byte Traffic beim Aufruf des Screens mit der Gallery. Nehmen wir nun ein Ticketsystem mit sagen wir mal 2000 Einträgen, so kommen wir (Attachments mal nicht mitgerechnet) auf 3,3 MB.
Folgen wir der Rechnung der folgenden Quelle, so kommen wir auf 3,4g CO2-Emission bezogen auf den Datentransfer, sollten alle Datensätze auf einen Schlag geladen werden, was z.B. im Falle eines Delegation-Issue der Fall wäre. Das dann doch eine recht ordentliche Menge zusammenkommt, brauche ich nicht weiter zu vertiefen.
https://docs.microsoft.com/en-us/learn/modules/sustainable-software-engineering-overview/8-network-efficiency
Und falls das nicht reicht, so tut es einfach für Eure User, denn niemand wartet gerne unnötig lange auf Daten.
Ein Schmankerl zum Abschluss
Ist Euch aufgefallen, dass im Monitor auch immer eine Abfrage der Attachments ausgeführt wird? Zur Erinnerung: Ich war immer nur auf dem ersten Screen der App, dem Browse-Screen.

Das liegt daran, dass im Edit-Screen der App (Zwei Klicks weiter!) die Attachments hochgeladen werden können und somit das Feld auch jetzt schon abgefragt wird:

Lösche ich die DataCard aus dem Formular dieses Screens fallen auch keine Datentransfers bei dem Besuch des Browse-Screens an. Doch damit beschäftige ich mich später.
Ich hoffe, dass Euch meine Ideen helfen, eine CO2-optimierte App zu erstellen. Verbesserungsvorschläge und Fragen sind willkommen, gerne per Twitter (@PapaRiedel) oder LinkedIn.
Viel Freude damit!