Docs
搜索⌘ K
  • 主页
  • 关于 The Graph
  • 支持的网络
  • 协议合约
  • 子图
    • 子流
      • 代币 API
        • AI Suite
          • 索引
            • 资源
              子图 > 最佳实践

              6 分钟

              子图最佳实践3-通过使用Immutable Entities和Bytes作为ID来提高索引和查询性能

              TLDR

              在schema.graphql文件中使用Immutable Entities和Bytes作为ID显著改进索引速度和查询性能。

              不可变实体

              为了使一个实体不可变,我们只需在实体中添加(immutable:true)。

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

              通过使Transfer实体不可变,graph-node能够更有效地处理实体,提高索引速度和查询响应能力。

              Immutable Entities structures will not change in the future. An ideal entity to become an Immutable Entity would be an entity that is directly logging on-chain event data, such as a Transfer event being logged as a Transfer entity.

              在后台

              可变实体有一个块范围表示其有效性。更新这些实体需要graph节点调整以前版本的块范围,从而增加数据库工作负载。查询还需要筛选,以便只找到活动实体。不可变实体更快,因为都是活的,而且不会改变,在写入时不需要检查或更新,在查询时也不需要筛选。

              何时不使用不可变实体

              如果你有一个类似字段的状态需要随着时间的推移而修改,那么你不应该让实体不可变。否则,您应该尽可能使用不可变实体。

              字节作为ID

              每个实体都需要一个ID。在前面的示例中,我们可以看到ID已经是Bytes类型。

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

              虽然其他类型的ID也是可能的,如String和Int8,但建议对所有ID使用Bytes类型,因为字符串存储二进制数据所需的空间是Byte字符串的两倍,并且UTF-8字符串的比较必须考虑到区域设置,这比用于比较Byte串的逐字节比较要昂贵得多。

              不使用字节作为ID的原因

              1. 如果实体ID必须是人类可读的,例如自动递增的数字ID或可读字符串,则不应使用Bytes 作为 ID。
              2. 如果将子图的数据与不使用Bytes作为ID的另一个数据模型集成,则不应使用Bytes 作为 ID。
              3. 索引和查询性能的改进是不可取的。

              以Bytes作为ID连接

              在许多子图中,使用字符串连接将事件的两个属性组合成一个ID是一种常见的做法,例如使用event.transaction.hash.toHex()+“-”+event.logIndex.toString()。然而,由于这会返回一个字符串,将严重阻碍子图索引和查询性能。

              相反,我们应该使用concatI32()方法来连接事件属性。此策略产生了性能更高的BytesID。

              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}

              以Bytes作为ID排序

              如本示例查询和响应所示,使用字节作为ID进行排序不是最佳选择。

              查询:

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

              查询响应:

              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}

              ID以十六进制返回。

              为了改进排序,我们应该在BigInt实体上创建另一个字段。

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

              这将允许按顺序优化排序。

              查询:

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

              查询响应:

              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}

              结论

              使用Immutable Entities和Bytes作为ID已被证明可以显著提高子图效率。具体来说,测试表明查询性能提高了28%,索引速度提高了48%。

              在Edge&Node的软件工程师David Lutterkort的这篇博客文章中,可以阅读到更多关于使用Immutable Entities和字节作为ID的信息:两个简单的子图性能改进。

              子图最佳实践1-6

              1. 通过子图修剪提高查询速度

              2. 使用@derivedFrom提高索引和查询响应能力

              3. 通过使用不可变实体和字节作为ID来提高索引和查询性能

              4. 通过避免eth_calls提高索引速度

              5. 通过时间序列和聚合进行简化和优化

              6. 使用嫁接快速部署修补程序

              ⁠在GitHub上编辑⁠

              带有@derivedFrom的数组避免eth_calls
              在此页面上
              • TLDR
              • 不可变实体
              • 在后台
              • 何时不使用不可变实体
              • 字节作为ID
              • 不使用字节作为ID的原因
              • 以Bytes作为ID连接
              • 以Bytes作为ID排序
              • 结论
              • 子图最佳实践1-6
              The GraphStatusTestnetBrand AssetsForum安全Privacy PolicyTerms of Service