Docs
La Recherche⌘ K
  • Accueil
  • À propos de The Graph
  • Réseaux pris en charge
  • Contrats du Protocole
  • Subgraphs
    • Substreams
      • Token API
        • AI Suite
          • Indexing
            • Resources
              Subgraphs > Les meilleures pratiques

              5 minutes

              Bonne pratique pour les subgraphs 3 - Améliorer l'Indexation et les Performances de Recherche en Utilisant des Entités Immuables et des Bytes comme IDs

              TLDR

              Utiliser des Entités Immuables et des Bytes pour les IDs dans notre fichier schema.graphql améliore considérablement la vitesse d’indexation et les performances de recherche.

              Entités Immuables

              Pour rendre une entité immuable, il suffit d’ajouter (immutable: true) à cette entité.

              1type Transfer @entity(immutable: true) {2  id: Bytes!3  from: Bytes!4  to: Bytes!5  value: BigInt!6}

              En rendant l’entité Transfer immuable, graph-node est capable de traiter l’entité plus efficacement, améliorant la vitesse d’indexation et la réactivité des requêtes.

              Les structures des entités immuables ne changeront pas dans le futur. Une entité idéale pour devenir une Entité immuable serait une entité qui enregistre directement les données d’un événement onchain, comme un événement Transfer enregistré en tant qu’entité Transfer.

              Sous le capot

              Les entités mutables ont une “plage de blocs” indiquant leur validité. La mise à jour de ces entités nécessite que le graph node ajuste la plage de blocs des versions précédentes, augmentant la charge de travail de la base de données. Les requêtes nécessitent également un filtrage pour trouver uniquement les entités actives. Les entités immuables sont plus rapides car elles sont toutes actives et, puisqu’elles ne changeront pas, aucun contrôle ou mise à jour n’est requis lors de l’écriture, et aucun filtrage n’est requis pendant les requêtes.

              Quand ne pas utiliser les Entités Immuables

              Si vous avez un champ comme status qui doit être modifié au fil du temps, alors vous ne devriez pas rendre l’entité immuable. Autrement, vous devriez utiliser des entités immuables dès que possible.

              Bytes comme IDs

              Chaque entité nécessite un ID. Dans l’exemple précédent, nous pouvons voir que l’ID est déjà du type Bytes.

              1type Transfer @entity(immutable: true) {2  id: Bytes!3  from: Bytes!4  to: Bytes!5  value: BigInt!6}

              Bien que d’autres types d’ID soient possibles, tels que String et Int8, il est recommandé d’utiliser le type Bytes pour tous les IDs en raison des chaînes de caractères prenant deux fois plus d’espace que les chaînes Byte pour stocker des données binaires, et les comparaisons de chaînes de caractères UTF-8 doivent tenir compte de la locale, ce qui est beaucoup plus coûteux que la comparaison binaire utilisée pour comparer les chaînes de caractères Byte.

              Raisons de ne pas utiliser les Bytes comme IDs

              1. Si les IDs d’entité doivent être lisibles par les humains, comme les IDs numériques auto-incrémentés ou les chaînes lisibles, les Bytes pour les IDs ne doivent pas être utilisés.
              2. Si vous intégrez les données d’un Subgraph dans un autre modèle de données qui n’utilise pas les Bytes en tant qu’ID, il ne faut pas utiliser les Bytes en tant qu’ID.
              3. Les améliorations de performances d’indexation et de recherche ne sont pas souhaitées.

              Concatenation Avec Bytes comme IDs

              Dans de nombreux subgraphs, il est courant d’utiliser la concaténation de chaînes pour combiner deux propriétés d’un événement en un seul identifiant, par exemple en utilisant event.transaction.hash.toHex() + "-" + event.logIndex.toString(). Cependant, comme cette méthode renvoie une chaîne de caractères, elle entrave considérablement les performances d’indexation et d’interrogation du Subgraph.

              Au lieu de cela, nous devrions utiliser la méthode concatI32() pour concaténer les propriétés des événements. Cette stratégie donne un ID de type Bytes beaucoup plus performant.

              1export function handleTransfer(event: TransferEvent): void {2  let entity = new Transfer(event.transaction.hash.concatI32(event.logIndex.toI32()))3  entity.from = event.params.from4  entity.to = event.params.to5  entity.value = event.params.value67  entity.blockNumber = event.block.number8  entity.blockTimestamp = event.block.timestamp9  entity.transactionHash = event.transaction.hash1011  entity.save()12}

              Tri avec Bytes comme IDs

              Le tri utilisant les Bytes comme IDs n’est pas optimal, comme le montre cet exemple de requête et de réponse.

              Requête:

              1{2  transfers(first: 3, orderBy: id) {3    id4    from5    to6    value7  }8}

              Réponse de la requête:

              1{2  "data": {3    "transfers": [4      {5        "id": "0x00010000",6        "from": "0xabcd...",7        "to": "0x1234...",8        "value": "256"9      },10      {11        "id": "0x00020000",12        "from": "0xefgh...",13        "to": "0x5678...",14        "value": "512"15      },16      {17        "id": "0x01000000",18        "from": "0xijkl...",19        "to": "0x9abc...",20        "value": "1"21      }22    ]23  }24}

              Les IDs sont renvoyés sous forme hexadécimale.

              Pour améliorer le tri, nous devrions créer un autre champ sur l’entité qui est un BigInt.

              1type Transfer @entity {2  id: Bytes!3  from: Bytes! # address4  to: Bytes! # address5  value: BigInt! # unit2566  tokenId: BigInt! # uint2567}

              Ceci permettra d’optimiser le tri de manière séquentielle.

              Requête:

              1{2  transfers(first: 3, orderBy: tokenId) {3    id4    tokenId5  }6}

              Réponse de la requête:

              1{2  "data": {3    "transfers": [4      {5        "id": "0x…",6        "tokenId": "1"7      },8      {9        "id": "0x…",10        "tokenId": "2"11      },12      {13        "id": "0x…",14        "tokenId": "3"15      }16    ]17  }18}

              Conclusion

              L’utilisation d’entités immuables et de Bytes comme IDs a permis d’améliorer sensiblement l’efficacité de Subgraph. Plus précisément, les tests ont mis en évidence une augmentation de 28 % des performances des requêtes et une accélération de 48 % des vitesses d’indexation.

              En savoir plus sur l’utilisation des Entités immuables et des Bytes en tant qu’IDs dans cet article de blog de David Lutterkort, un ingénieur logiciel chez Edge & Node : Deux améliorations simples des performances des subgraphs.

              Bonnes pratiques pour les subgraphs 1-6

              1. Améliorer la vitesse des requêtes avec l’élagage des Subgraphs

              2. Améliorer l’indexation et la réactivité des requêtes en utilisant @derivedFrom

              3. Améliorer l’indexation et les performances des requêtes en utilisant des entités immuables et des Bytes comme IDs

              4. Améliorer la vitesse d’indexation en évitant les eth_calls

              5. Simplifier et optimiser avec les séries chronologiques et les agrégations

              6. Utiliser le greffage pour un déploiement rapide des correctifs

              ⁠Edit on GitHub⁠

              Tableaux avec @derivedFromÉviter les eth_calls
              On this page
              • TLDR
              • Entités Immuables
              • Sous le capot
              • Quand ne pas utiliser les Entités Immuables
              • Bytes comme IDs
              • Raisons de ne pas utiliser les Bytes comme IDs
              • Concatenation Avec Bytes comme IDs
              • Tri avec Bytes comme IDs
              • Conclusion
              • Bonnes pratiques pour les subgraphs 1-6
              The GraphStatusTestnetActifs de la MarqueForumSécuritéPolitique de confidentialitéConditions d'utilisation