头图

深入The Graph数据库

blockgeek

The Graph网络对Web3的查询层和API层进行了去中心化,消除了DApp开发者目前面临的取舍难题:到底是开发一个高性能应用,还是开发一个完全去中心化的应用。目前,开发者可以在自己的基础架构上运行一个Graph节点,也可以在我们的托管服务上开发一个。其中,开发者构建和部署从Web3数据源提取数据并为其编制索引的子图。目前已经有许多领先的以太坊项目创建了子图,包括Uniswap、ENS、DAOstack、Synthetix和Moloch等。在The Graph网络中,任何索引器都能够通过抵押Graph代币(GRT)参与到网络中,并在提供查询服务的过程赚取费用和通货膨胀奖励。用户则按照使用次数进行付费,使用日益增长的索引器,此做法证明了供需规律也适用于该协议提供的服务。

The Graph 简单理解相当于是区块链上面的搜索引擎,爬取区块链上的区块数据, 然后根据用户制定的规则进行搜索,方便各个DApp查询。

本文将深入The Graph的数据库,看看The Graph是怎么实现数据存储的。

The Graph表结构

上面是The Graph的数据库结构。

  • subgraph是个核心数据库,里面存放着所有子图的基础信息;
  • 每当创建一个新的子图的时候, 就会有一个新的数据库产生,比如上图中sgd1是給第一个子图的数据库, 数据库名字按序号递增。

Subgraph数据库存储

每次新创建的subgraph会存放在下面表中

新创建subgraph的时候会有些的数据库生成, 专门用来存放该subgraph里面定义的schema。

如果上传的subgraph的文件没有发生变化, 则不会重新生成新的数据库。

以下是一些核心的表:

  • subgraph: 存放subgraph的基本信息,比如名字,创建时间, block range等;
  • subgraph_deployment:存放subgraph的布署信息以及和区块链的同步信息, 比如最早和最迟的区块号等;
  • subgraph_error: 子图在布署过程中碰到的一些错误。

每个subgraph的存储

每个subgraph自己的数据库里面,存放着子图里面schema entity对应的表。 每个子图定义的entity对应一张表,表结构对应entity的结构。 比如下面这个entity的定义:

type Token @entity {
  # token address
  id: ID!

  # mirrored from the smart contract
  symbol: String!
  name: String!
  decimals: BigInt!

  # used for other stats like marketcap
  totalSupply: BigInt!

  # token specific volume
  tradeVolume: BigDecimal!
  tradeVolumeUSD: BigDecimal!
  untrackedVolumeUSD: BigDecimal!

  # transactions across all pairs
  txCount: BigInt!

  # liquidity across all pairs
  totalLiquidity: BigDecimal!

  # derived prices
  derivedETH: BigDecimal

  # derived fields
  tokenDayData: [TokenDayData!]! @derivedFrom(field: "token")
  pairDayDataBase: [PairDayData!]! @derivedFrom(field: "token0")
  pairDayDataQuote: [PairDayData!]! @derivedFrom(field: "token1")
  pairBase: [Pair!]! @derivedFrom(field: "token0")
  pairQuote: [Pair!]! @derivedFrom(field: "token1")
}

对应的表结构

CREATE TABLE "sgd1"."token" (
  "id" text COLLATE "pg_catalog"."default" NOT NULL,
  "symbol" text COLLATE "pg_catalog"."default" NOT NULL,
  "name" text COLLATE "pg_catalog"."default" NOT NULL,
  "decimals" numeric NOT NULL,
  "total_supply" numeric NOT NULL,
  "trade_volume" numeric NOT NULL,
  "trade_volume_usd" numeric NOT NULL,
  "untracked_volume_usd" numeric NOT NULL,
  "tx_count" numeric NOT NULL,
  "total_liquidity" numeric NOT NULL,
  "derived_eth" numeric,
  "vid" int8 NOT NULL DEFAULT nextval('"sgd1".token_vid_seq'::regclass),
  "block_range" int4range NOT NULL
)

我们可以看到,除了entity里面定义的字段之外,表里面还有 "vid", 还有 "block_range"字段,这2个字段主要是用来做数据的版本控制的。也就是同一个id的数据,每次里面字段发生变化的时候都会产生一个新的版本。

版本控制

The Graph的数据表会自动对每条记录进行版本的迭代。比如下面例子中, 其实是同一条数据的不同版本,因为其Id 一致的代表是同一条数据, "block_range"标明了某个数据版本的有效区块区间。

这样的做法可以记录同一个id的数据随着区块的变化产生的版本变化,也可追溯到历史版本,保证了历史数据的不丢失。

作者:Bernie
原文链接:http://blockgeek.com/129d/3ad7


欢迎区块链行业志同道合的小伙伴添加小极微信,加入blockgeek区块链技术交流群,共同推动区块链技术普及和发展~

image.png

阅读 215
1 声望
2 粉丝
0 条评论
你知道吗?

1 声望
2 粉丝
宣传栏