Direkt zum Hauptbereich

Sprechen Sie APEXisch? Kapitel "Sicherer Umgang mit Datenflut".

Seit knapp 1,5 Jahren beschäftige ich mich intenisv mit Salesforce. Die Robustheit des Systems im Umgang mit gigantischen Datenmengen fasziniert mich immer wieder. Als ehemaliger Lotus Notes Entwickler vergleiche ich zwangsweise unbewusst diverse Aktivitäten und die damit verbundenen Aufwände in Bezug auf die Datenintegration und -bearbeitung in den beiden Systemen miteinander. Es macht wenig Sinn, ein dokumentorientiertes Datenbanksystem mit einem Relationalen aus der technischen Perspektive zu vergleichen. Außerdem ist ein Vergleich nicht die primäre Intention dieses Beitrags. Viel mehr möchte ich meinen Gesamteindruck fokussiert auf einen Tagesausschnitt vermitteln, indem ich mich auf die Beschreibung eines technischen Problems und der Lösungssuche dazu beschränke.

Ausgangslage:
Beim Speichern eines Datensatzes startet der entsprechende Trigger und …
beendet seine Arbeit mit einer Fehlermeldung.

Fehlermeldung
System.QueryException: Non-selective query against large object type (more than 100000 rows)….

Analyse
Der Übeltäter ist schnell identifiziert. Die folgende Datenbankabfrage liefert insgesamt 200.000 Datensätze, trotz der gesetzten Limitierung auf 1.000. 
'SELECT id FROM myObject WHERE isInUse__c=true Limit 1000
Im 1. Schritt einer Datenbankabfrage werden alle Suchergebnisse unbeachtet der Limitierung zur Verfügung gestellt, und erst anschließend wird die Anzahl auf das Limit reduziert. 
Da die Anzahl der gefundenen Datensätze die von Salesforce definierte Obergrenze von 100.000 überschreitet, wird mein Trigger außer Gefecht gesetzt. 

Lösung
Salesforce bietet eine gigantische Auswahl an mächtigen Werkzeugen, wie Data Loader, Lexi Loader, Import Wizard, Dataloader.io (mehr dazu hat mein Kollege Tobias gepostet http://www.cloudblogger.de/2013/12/salesforce-integration-fuer-arme/). Diese Werkzeuge sind in der Lage, performant und zuverlässig mit großem Datenbestand umzugehen. Sie alle „jonglieren“ mit Leichtigkeit mit diversen Salesforce APIs wie z.B. REST, BULK, SOAP, deren Basis die APEX-Sprache bildet. 
Mein Trigger basiert ebenfalls auf APEX. Es muss also eine simple Lösung für mein Problem geben. Die unglaublich starke Salesforce Community bietet eine beeindruckende Unterstützung mit vielen Anleitungen, Tipps und gezielten Antworten. Die Suche nach einem Lösungsansatz dauert nicht lange. Zusätzlicher Blick in die Salesforce Hilfe kombiniert mit ein paar Tests sind vielversprechend.

Folgende Techniken kommen als mögliche Lösungen in Frage:
1) SOSL = Salesforce Object Search Language
Nutze SOSL, um Text-, Email-, Telefonfelder aller Objekte durchzusuchen. Mit dem Schlüsselwort RETURNING können anschließend nur bestimmte Objekte für die weitere Verarbeitung herangezogen werden.

Beispiel: 
List<List<SObject >>searchList = [FIND 'mein suchstring*'in ALL FIELDS RETURNING myObject (Id, Name, isInUse__c WHERE isInUse__c = false) Limit 200];
for(myObject v :((List<myObject>)searchList[0])){
    //… hier startet die Verarbeitung ...
}
Nachteil dieser Lösung:
- ich muss zusätzlich ein Textfeld mit einem bestimmten Wert implementieren.

2) SOQL = Salesforce Object Query Language
Nutze SOQL, um gezielt nach einem bestimmten Objekt zu suchen. Um große Datenbestände durchzusuchen, markiere das Feld aus dem WHERE Block als „External ID“. 
externalId

Beispiel:
for(myObject v : [SELECT id FROM myObject WHERE isActive__c=1 Limit 1000]){
    //… hier startet die Verarbeitung ...

}

Die 2. Option erfordert weniger Aufwand in Bezug auf die Implementierung und entspricht mehr dem aktuellen Einsatzzweck. Statt isInUse__c (Kontrollkästchen) setze ich ein neues Feld isActive__c (Zahl) ein. Dieses Feld fungiert als externe ID. Somit lässt sich die Datenbank auch mit 200.000 relevanten Ergebnissen erfolgreich und dank der Indizierung des neuen Feldes performant durchsuchen.


Hier die beiden Techniken ausführlich erklärt:
http://salesforce.stackexchange.com/questions/9028/soql-vs-sosl-which-one-to-use-and-when

Kommentare

Beliebte Posts aus diesem Blog

Salesforce.com Certified Advanced Administrator (WI15)

Im Vergleich zu den beiden Consultants Zertifizierungen war die Advanced Admin ein Spaziergang!
Allerdings ganz ohne Vorbereitung schafft man die Prüfung auch nicht.


Hier sind einige Fragen/Antworten aus der aktuellen Prüfung.

1. Capabilities of collaborative forecasting?
- Rename categories
- Forecast using opportunity splits
- Overlay Quota
- Add categories
- Select a default forecast currency setting

2. We have four Sales Regions. Each of the region's VPs wants to have a dashboard emailed every Monday.
- Create a separate dashboard for each VP
- Create one dashboard using Visualforce
- Create one dashboard that includes a filter for each region
- Create a reporting snapshot

3. User is trying to access content in a library, but receiving an insufficent privileges message.
How to troubleshoot?
- has the user's profile the CRM content permission enabled
- user has been granted permission "Viewer" to the library
- user's record has the CRM content permisson enabled
- …

Salesforce - Datensätze sperren (Umsetzung)

Record Lock - nun, die Umsetzung.Wir haben bereits mehrere VisualForce Pages im Einsatz. Aus dem Grund ist das zuvor beschriebene Konzept darauf zugeschnitten. Selbstverständlich lässt sich der Code auch für Standard und Custom Objects verwenden, ohne den Einsatz von VisualForce Pages. Na ja, mindestens eine VF Page brauchen wir eigentlich schon - diejenige, die von dem dem "Edit" Button aufgerufen wird.

Ich zeige jetzt die wichtigsten Bausteine aus der Umsetzung.
1) Diese VF Page wird aufgerufen sobald man den "Edit" Button betätigt

<apex:pagestandardController="myObject"title="{!myObject.Name}"extensions="LockController"action="{!SwitchToPage}">
<!-- READ MODE --> <apex:includepageName="myObjectRead"rendered="{!isEditMode == false}"/>
<!-- EDIT MODE --> <apex:includepageName="myObjectEdit"rendered="{!isEditMode == true}"/>
</apex:page>

Folgendes passiert …

Emails mit APEX | SINGLE_EMAIL_LIMIT_EXCEEDED

Email-Versand mit Visualforce und Apex kann schon manchmal Kopfschmerzen bereiten....

Entweder ist die Email zu groß, oder zu viele Attachments oder der HeapSize "beschwert sich" oder, wenn letztendlich alles läuft,  man wird von den Salesforce Limits zurück zum Ausgangspunkt katapultiert.

Das kann doch nicht so schwer sein!
Ist es auch nicht, wenn man das schon einmal gemacht hat ;-)

Habe eine Visualforce Maske zum Versenden von HTML Emails programmiert.
Diese werden als SingleEmailMessage gesendet:
Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
Sobald die Anzahl der pro Tag gesendeten Emails den Salesforce Limit "knackt", wird dem User die entsprechende Meldung eingeblendet.



Die auf die Org bezogene Limitierung lässt sich mit LIMITS.getLimitEmailInvocations() berechnen.

Hier ein Auszug aus den "Execution Governors and Limits"
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

A Dev Edition org ha…