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

                  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