Modèles d’évolutivité

En savoir plus sur la fiabilité bien archivée → Évolutivité et planification des capacités

Modèles

Où chercherÀ quoi ressemble le bien
Efficacité des requêtes SOQLConsolidez les requêtes en utilisant des requêtes de relation (Contacts, Cases__r) au lieu de requêtes séparées par objet associé. Interrogez toutes les données requises une fois par transaction. Ciblez <50 requêtes dans des transactions synchrones, <100 en asynchrone (limites : 100 synchronisés, 200 asynchrones). Maintenez une marge tampon de 30 à 50 % inférieure aux limites.
Massification des opérations DMLCollectez des enregistrements dans des listes, exécutez une instruction DML unique par type d’objet et par transaction. Utilisez Database.insert/update/delete avec le paramètre allOrNone qui contrôle le comportement de réussite partielle. Cible <75 instructions DML par transaction (limite : 150). Le lot réduit la consommation de DML de N instructions à 1.
Gestion de la taille du tasInterrogez uniquement les champs obligatoires (évitez les modèles SELECT *). Traitez les grands ensembles de résultats par segments. Effacez les collections après traitement pour libérer la mémoire. Heap cible <4 Mo en contexte synchrone (limite : 6 Mo), <8 Mo asynchrone (limite : 12 MO). Les erreurs de dépassement de tas indiquent la nécessité de segments ou de modèles de streaming.
Optimisation du temps processeurRéduisez la complexité des calculs dans les boucles. Utilisez Maps pour les références (O(1)) au lieu de l’itération Liste imbriquée (O(n2)). Déchargez le calcul lourd du contexte asynchrone. CPU cible <7 000 ms dans les transactions synchrones (limite : 10 000 ms), < 40 000 ms asynchrone (limite : 60 000 ms).
Lignes de requête SOQLConcevez des requêtes renvoyant des tailles d’ensemble de résultats raisonnables. Utilisez la clause LIMIT pour plafonner les résultats. Cible <25 000 lignes par requête en contexte synchrone (limite : 50,000). Les requêtes approchant les limites doivent utiliser la pagination ou passer au traitement asynchrone avec Apex par lot ou Queueable.
Allocation d’appels d’APISurveillez la consommation d’API limite sur 24 heures via Vue d’ensemble du système. Opérations d’API par lot au lieu d’appels enregistrement par enregistrement. La mise en cache accédait fréquemment aux données de référence en utilisant Cache de la plate-forme. Ciblez <70 % de la limite quotidienne en API pour tenir compte des pics. La limite en API varie selon l’édition et le nombre de licences.
Limites en appels externesConsolider les appels externes : plusieurs enregistrements par lot dans une seule requête d’API lorsque le système externe la prend en charge. Implémentez la mise en file d’attente des requêtes pour sérialiser les appels externes. Respectez le temps total d’appel externe de 120 secondes par transaction. Limite : 100 appels externes par transaction. Concevez un traitement asynchrone pour les intégrations lourdes en appels externes.
Code (Apex, Aura, LWC)Implémentez des modèles de traitement en masse : traiter les collections pas les enregistrements individuels, interroger une fois et mettre en cache dans Maps, exécuter un DML unique par type d’objet. Utilisez des requêtes de relation pour réduire la consommation de SOQL. Appliquez des algorithmes efficaces en évitant les boucles imbriquées dans des jeux de données volumineux.

Anti-modèles

Où chercherÀ quoi ressemble mal
SOQL en bouclesProblème : Exécution de requêtes SOQL dans des boucles de traitement de collections d’enregistrements. Impact : La limite en requêtes a dépassé l’erreur à plus de 100 enregistrements (limite : 100 requêtes par transaction). Résolution : Interrogez une fois avant la boucle, stockez les résultats dans le champ Mappé par relation. Référence de Map inside loop (modèle de transfert en masse).
DML en bouclesProblème : Exécution d’instructions insert/update/delete dans des boucles for. Impact : La limite en DML dépasse l’erreur dans plus de 150 enregistrements (limite : 150 instructions DML par transaction). Résolution : Collectez les enregistrements dans la boucle interne Liste, exécutez une instruction DML unique une fois la boucle terminée.
Pas de tampon de limite du gouverneurProblème : Concevoir des transactions consommant plus de 95 % des limites du gouverneur dans des conditions normales. Impact : Échecs de production lors de légères augmentations de charge, pas de capacité pour les cas de bord. Résolution : Ciblez 70 % des limites en tant que plafond opérationnel. Réservez 30 % de tampon pour les crampons et les étuis de bord.
Produits cartésiens en boucle imbriquéeProblème : Boucles imbriquées itérant deux grandes collections créant des opérations O(n2). Impact : La limite en processeur dépasse les erreurs, la limite en piles dépasse les objets temporaires. Résolution : Utilisez des références basées sur la carte qui convertissent O(n2) en O(n). Recueillez les clés de boucle externe, interrogez les enregistrements associés une fois, référencez dans la boucle interne.
Accumulation de tasProblème : Chargement des résultats de requête volumineux en mémoire sans traitement en segments. Impact : La limite du tas a dépassé l’erreur (6 Mo de synchronisation, 12 Mo asynchrone). Résolution : Interrogez uniquement les champs requis. Traiter par lots les collectes de compensation après chaque lot. Utilisez QueryLocator with Batch Apex pour le traitement de plusieurs millions d’enregistrements.
Aucun filtrage au niveau du champProblème : Sélection de tous les champs (explicites ou implicites) lorsque seul un sous-ensemble est requis. Impact : Consommation excessive de tas, exécution de requêtes plus lente, limite en lignes SOQL approchée inutilement. Résolution : SELECT uniquement les champs requis pour le traitement. Utilisez la notation des relations pour récupérer les données associées dans une seule requête plutôt que dans des requêtes séparées.
Surutilisation du traitement synchroneProblème : Traitement synchrone des volumes de données importants dans les transactions des utilisateurs. Impact : Utilisateur en attente d’opérations de plusieurs secondes, les limites en processeur/tas dépassaient l’utilisateur bloquant. Résolution : Déplacez le traitement lourd vers un contexte asynchrone (batch, file d’attente, événements de plate-forme). Fournissez une réponse immédiate à l’utilisateur avec un sondage de statut.

Modèles

Où chercherÀ quoi ressemble le bien
Traitement asynchroneUtilisez Apex par lot pour traiter les volumes d’enregistrement importants (millions). Utilisez Apex Queueable pour une orchestration complexe à plusieurs étapes avec chaînage. Utilisez Événements de plate-forme pour le découplage piloté par l’événement. Utilisez Scheduled Apex pour la maintenance périodique. Correspondance du schéma asynchrone avec le cas d’utilisation : Lot pour le volume, File d’attente pour la complexité, Événements pour le découplage.
Implémentation Apex par lotMéthode Design Start renvoyant un QueryLocator sélectif afin de minimiser les enregistrements traités. Configurez la taille du lot en fonction de la complexité des enregistrements (200 à 2000 enregistrements par exécution). Implémentez l’interface stateful uniquement si nécessaire pour réduire le débit. Surveillez la réussite/l’échec de AsyncApexJob. Le lot fournit des limites de gouverneur dédiées par segment.
Architecture des événements de plate-formePubliez les événements de changement d’état nécessitant un traitement en aval. Abonnez-vous en utilisant des déclencheurs Apex dans des objets d’événement de plate-forme ou des abonnés externes via CometD. Concevez des abonnés idempotents (la lecture peut livrer des événements plusieurs fois). Utilisez la rétention de 72 heures pour récupérer les échecs temporaires des abonnés.
Partitionnement basé sur la dateTraiter les données dans des fenêtres temporelles : mois en cours, trimestre dernier, cette année. Archivez les données historiques dans des Big Objects ou un stockage externe. Le partitionnement temporel permet de traiter simultanément différentes plages de dates par lots parallèles. La plupart des requêtes filtrent naturellement par date, ce qui est efficace.
Partitionnement du type d’enregistrementTraitez les différents types d’enregistrement indépendamment. Planifiez des tâches par lot séparées par type d’enregistrement pour activer la parallélisation. Les types d’enregistrement sont souvent corrélés à des processus métiers distincts justifiant un traitement indépendant. 5 tâches par lot simultanées maximum par organisation nécessitent un partitionnement stratégique.
Partitionnement géographiquePartition par propriétaire, division ou territoire pour traiter la distribution. Traitez chaque région, unité commerciale ou territoire commercial dans des tâches par lot parallèles. Le partitionnement géographique exploite le modèle de partage : chaque tâche par lot est exécutée dans le contexte d’un groupe d’utilisateurs spécifique qui filtre naturellement les données.
Stratégie de mise en cacheUtilisez Cache de la plate-forme (partitions d’organisation/session) pour les données de référence fréquemment accédées. Le cache réduit la consommation de requêtes et d’API. Allouez des partitions d’organisation et de session par incréments de Mo entiers. La capacité par défaut varie selon l’édition, avec une capacité supplémentaire achetable par bloc. Le manque de cache devrait gracieusement retomber dans la requête. Cache TTL doit correspondre à la fréquence de modification des données : heures pour les données de référence statiques, minutes pour semi-dynamiques.
Massification du fluxConcevez des flux traitant des collections d’enregistrements en utilisant des variables Boucle et Collection. Créer une collection d’enregistrements, effectuer des Obtenir des enregistrements uniques, mettre à jour la collection avec un seul élément Mettre à jour les enregistrements. Évitez les opérations d’enregistrement individuelles dans les boucles. Les modèles de traitement en masse des flux reflètent les meilleures pratiques Apex.

Anti-modèles

Où chercherÀ quoi ressemble mal
Traitement séquentiel uniquementProblème : Tâche par lot unique traitant les 50 millions d’enregistrements de façon séquentielle en plus de 24 heures. Impact : Bloque les autres traitements, l’épuisement des fenêtres de maintenance, les retards pour l’utilisateur. Résolution : Partitionnez les données par date, type d’enregistrement ou zone géographique. Exécutez simultanément des tâches par lot parallèles traitant des partitions indépendantes.
Dépendances d’intégration synchronesProblème : Les transactions utilisateur bloquées en attente de réponses système externes via des appels externes synchrones. Impact : Expérience utilisateur liée aux performances système externes, échecs d’expiration pendant les pannes externes. Résolution : Utilisez Événements de plate-forme pour l’intégration asynchrone. Dissociez la transaction utilisateur de la disponibilité du système externe.
Aucune couche de mise en cacheProblème : Interrogation répétée des mêmes données de référence entre les transactions. Impact : Consommation SOQL excessive, gaspillage de limite d’API, exécution de transaction ralentie. Résolution : Implémentez le cache de la plate-forme pour les données de référence fréquemment accédées. Le cache réduit la consommation limite du gouverneur et améliore les performances.
Empilage des tâches par lotProblème : Planification de 20 tâches par lot commençant simultanément. Impact : L’accumulation de profondeur de la file d’attente, 5 limites de tâches simultanées entraîne la sérialisation, des temps de réalisation imprévisibles. Résolution : Planifications échelonnées distribuant la charge sur plusieurs heures. Consolidez les tâches similaires en un seul lot avec une logique de répartition dynamique.
Surutilisation de lots avec étatProblème : Implémentation d’Apex batch avec Database.Stateful quand ce n’est pas obligatoire. Impact : La sérialisation inutile des variables de membre d’instance entre les invocations execute() et l’accumulation potentielle de tas à partir de l’état conservé. Résolution : Utilisez stateful uniquement lorsque state doit persister entre les invocations execute. Préférez les lots sans état afin d’éviter les surcoûts inutiles de numérotation d’état.
Conception de flux à thread uniqueProblème : Le traitement des flux enregistre individuellement dans Boucle avec des éléments individuels Obtenir/Mettre à jour l’enregistrement par itération. Impact : Le gouverneur limite la consommation proportionnelle au nombre d’enregistrements, aux échecs de transaction à l’échelle. Résolution : Collectez des enregistrements dans une variable de collection, effectuez des Obtenir des enregistrements uniques, mettez à jour la collection avec un seul élément Mettre à jour les enregistrements hors de la boucle.
Aucune stratégie de nouvelle tentative asynchroneProblème : Les tâches asynchrones échouées ne sont pas automatiquement réessayées, ce qui nécessite une intervention manuelle. Impact : Incohérences dans les données, charge opérationnelle manuelle, SLA manqués. Résolution : Implémentez une nouvelle tentative automatique avec un recul exponentiel. Utilisez Événements de plate-forme pour une file d’attente durable qui active la relecture. Surveillez AsyncApexJob et alertez sur les échecs durables.

Modèles

Où chercherÀ quoi ressemble le bien
Sélection par lot et file d’attenteUtilisez Apex par lot pour : traitement de millions d’enregistrements par segments, opérations en masse planifiées, migrations de données. Utilisez Apex Queueable pour : workflows d’intégration à plusieurs étapes avec chaînage, opérations nécessitant des paramètres d’objet complexes, tâches nécessitant une meilleure surveillance que @future. Apex asynchrone partage une limite de 250 000 exécutions par 24 heures (DailyAsyncApexExecutions) à travers Batch, Queueable, Future et Scheduled Apex, plutôt qu’une allocation spécifique à Queueable.
Enchaînement file d’attenteImplémentez des workflows à plusieurs étapes en mettant en file d’attente la tâche suivante depuis la méthode execute de la tâche actuelle. La chaîne active le traitement séquentiel : callout → réponse d’analyse → action de suivi de file d’attente. Une file d’attente maximum par exécution pouvant être mise en file d’attente empêche l’emballement des chaînes. Concevez des chaînes avec la détection de réalisation pour éviter les boucles infinies.
Utilisation de la méthode @futureUtilisez @future pour de simples opérations asynchrones ne nécessitant aucun paramètre complexe (primitifs uniquement) et aucun enchaînement. Limite : 50 appels @future par transaction Apex. @future fournit le schéma asynchrone le plus simple mais manque de visibilité: pas de surveillance des tâches, pas de chaînage, pas de paramètres complexes. Préférez Queueable pour un nouveau développement.
Optimisation Apex planifiéeRegroupez les opérations planifiées en une seule répartition de classe planifiable pour des gestionnaires spécifiques. 100 tâches planifiées maximum par organisation nécessitent une consolidation stratégique. Planifiez pendant les heures creuses pour réduire les conflits avec les opérations des utilisateurs. Utilisez Apex planifié pour l’orchestration, déléguez le traitement lourd à Apex par lot.
Relecture de l’événement de plate-formeConcevez des abonnés qui gèrent les scénarios de relecture : événements dupliqués après l’échec de l’abonné, événements d’écart après une panne prolongée. Maintenez le dernier ReplayId traité par abonné. Utilisez EventBus.getReplayId() pour détecter la relecture par rapport aux nouveaux événements. Implémentez un traitement idempotent (traiter deux fois le même événement produit le même résultat).
Schéma de continuationUtilisez Continuation pour les appels externes de longue durée à partir de composants Lightning nécessitant des temps de réponse supérieurs à 5 secondes. La continuation active plusieurs appels externes simultanés de 120 secondes, ce qui améliore les performances perçues pour les opérations parallèles. Limite : 3 continuations par requête. Implémentez le traitement de l’expiration et les commentaires des utilisateurs.

Pour des exemples en ligne et des conseils détaillés, consultez le pilier Fiabilité ou parcourez l’explorateur Modèles et anti-modèles.