Utilisation de très grandes requêtes SOQL

Votre requête SOQL peut renvoyer de nombreux sObjects qui dépassent la limite de la taille de segment mémoire et génèrent une erreur. Pour la résoudre, utilisez une boucle for de requête SOQL, qui peut traiter plusieurs lots d'enregistrements en utilisant des appels internes à query et à queryMore.

Par exemple, si les résultats sont trop grands, la syntaxe ci-dessous peut entraîner une exception d'exécution.

Account[] accts = [SELECT Id FROM Account];

À la place, utilisez une boucle for de requête SOQL dans l'un des exemples ci-dessous :

// Use this format if you are not executing DML statements 
                    

// within the for loop

for (Account a : [SELECT Id, Name FROM Account WHERE Name LIKE 'Acme%']) { // Your code without DML statements here } // Use this format for efficiency if you are executing DML statements

// within the for loop

for (List<Account> accts : [SELECT Id, Name FROM Account WHERE Name LIKE 'Acme%']) { // Your code here

    update accts; }

L'exemple suivant montre une boucle for de requête SOQL utilisée pour mettre à jour en masse les enregistrements. Supposons que vous souhaitez modifier le nom de contact dans tous les enregistrements de contact dont le nom et le prénom correspondent à un critère spécifique :

public void massUpdate() {

    for (List<Contact> contacts:

      [SELECT FirstName, LastName FROM Contact]) {

        for(Contact c : contacts) {

            if (c.FirstName == 'Barbara' &&

              c.LastName == 'Gordon') {

                c.LastName = 'Wayne';

            }

        }

        update contacts;

    }

}

Au lieu d'utiliser une requête SOQL dans une boucle for, la méthode recommandée de mise à jour en masse des enregistrements consiste à utiliser Apex par lot, qui réduit les risques d'atteindre les limitations du gouverneur.

Pour plus informations, reportez-vous à Boucles For SOQL.

Requêtes SOQL plus efficaces

Pour de meilleures performances, les requêtes SOQL doivent être sélectives, notamment pour les requêtes dans des déclencheurs. Pour éviter les délais d'exécution importants, les requêtes SOQL non sélectives peuvent être terminées par le système. Les développeurs reçoivent un message d'erreur lorsqu'une requête non sélective dans un déclencheur est exécutée sur un objet qui contient plus de 100 000 enregistrements. Pour éviter cette erreur, assurez-vous d'utiliser une requête sélective.

Critères de requête SOQL sélective
  • Une requête est sélective lorsque l'un des filtres de requête se trouve dans un champ indexé et que le filtre de requête maintient le nombre de lignes généré sous le seuil défini par le système. Les performances de la requête SOQL augmentent lorsque deux filtres ou plus utilisés dans la clause WHERE remplissent les conditions spécifiées.
  • Le seuil de sélectivité est de 10 % des enregistrements pour le premier million d'enregistrements, et moins de 5 % des enregistrements à compter du premier million d'enregistrements, jusqu'à un maximum de 333 000 enregistrements. Dans certains cas, par exemple lorsqu'un filtre de requête se trouve dans un champ standard indexé, le seuil peut être plus élevé. En outre, le seuil de sélectivité peut être modifié.
Considérations sur les index personnalisés pour des requêtes SOQL sélectives
  • Les champs suivants sont indexés par défaut : clés primaires (champs ID, Nom et Propriétaire), clés étrangères (champs de référence ou de relation principal-details), dates d'audit (telles que LastModifiedDate) et champs personnalisés marqués en tant qu'ID externe ou Unique.
  • Les champs non indexés par défaut peuvent être automatiquement indexés ultérieurement si l'optimiseur Salesforce détermine qu'un index peut améliorer les performances des requêtes fréquemment exécutées.
  • Le support Salesforce.com peut ajouter des index personnalisés aux requêtes pour les clients.
  • Il n'est pas possible de créer un index personnalisé dans les types de champ suivants : listes de sélection multiple, champs de devise dans une organisation multidevises, champs de texte longs, certains champs de formule et champs binaires (champs de type blob, fichier ou texte crypté). Notez que de nouveaux types de données, généralement complexes, peuvent être ajoutés à Salesforce et leurs champs peuvent ne pas autoriser l'indexation personnalisée.
  • Généralement, un index personnalisé n'est pas utilisé dans les cas suivants :
    • La ou les valeurs demandées dépassent le seuil défini par le système évoqué plus haut.
    • L'opérateur de filtrage est un opérateur négatif, tel que NOT EQUAL TO (ou !=), NOT CONTAINS et NOT STARTS WITH.
    • L'opérateur CONTAINS est utilisé dans le filtre et le nombre de lignes à scanner dépasse 333 000, car l'opérateur CONTAINS nécessite un scan complet de l'index. Notez que ce seuil peut être modifié.
    • Lors d'une comparaison avec une valeur vide (Name != '').

    Cependant, il existe d'autres scénarios complexes dans lesquels les index personnalisés ne sont pas utilisés. Si votre cas n'est pas mentionné ici ou si vous souhaitez obtenir une aide supplémentaire sur les requêtes non sélectives, contactez votre représentant salesforce.com.

Exemples de requêtes SOQL sélectives
Pour mieux comprendre si une requête sur un objet volumineux est sélective ou non, analysons quelques requêtes. Pour ces requêtes, supposons qu'il existe 100 000 enregistrements (qui comprennent les enregistrements supprimés provisoirement, c.-à-d. présents dans la Corbeille) pour le sObject Account.
Requête 1 :
SELECT Id FROM Account WHERE Id IN (<list of account IDs>)

La clause WHERE se trouve dans un champ indexé (ID). Si SELECT COUNT() FROM Account WHERE Id IN (<list of account IDs>) renvoie un nombre d'enregistrements inférieur au seuil de sélectivité, l'index dans ID est utilisé. Ce cas est le plus fréquent, car la liste d'ID contient une faible quantité d'enregistrements.

Requête 2 :
SELECT Id FROM Account WHERE Name != ''

Puisque Account est un objet volumineux, même si Name est indexé (clé primaire), ce filtre renvoie la plupart des enregistrements, rendant la requête non sélective.

Requête 3 :
SELECT Id FROM Account WHERE Name != '' AND CustomField__c = 'ValueA'

Ici nous devons déterminer si chaque filtre, considéré individuellement, est sélectif. Comme nous l'avons vu dans l'exemple précédent, le premier filtre n'est pas sélectif. Examinons le deuxième. Si le nombre d'enregistrements renvoyé par SELECT COUNT() FROM Account WHERE CustomField__c = 'ValueA' est inférieur au seuil de sélectivité, et que CustomField__c est indexé, la requête est sélective.

© Copyright 2000–2013 salesforce.com, inc. Tous droits réservés.
Diverses marques de commerce appartenant à leur détenteur respectif.