サブグラフのパフォーマンスを改善する2つの機能

Edge & NodeとThe Graphコミュニティは、サブグラフのインデックス作成とクエリのパフォーマンスの向上に重点を置いています。Edge & Nodeは最近、この分野で役立つ2つの機能、「不変のエンティティ」と「エンティティのidとしてBytesを使用する」機能を完成させました。この2つの機能は互いに独立しており、immutableエンティティはsubgraphスキーマを少し変更するだけでよく、idとしてbyte文字列を使用する場合はマッピングを少し変更するだけで実行できます。
これらの拡張はインデックス作成の速度を向上させ、サブグラフのために保存する必要のあるデータ量を減らし、クエリを高速化します。インデックス作成速度の向上は、サブグラフがデータベースへのデータ書き込みに費やす時間が、コントラクト呼び出しやデータベースからのエンティティの読み取りなどの操作に依存します。
新機能は、現在ホストサービス上に展開されており、graph-nodeバージョン0.26.0のリリースに含まれる予定です。また、サブグラフの作者は、これらの機能を使用するために、バージョン0.28のgraph-cliとバージョン0.26のgraph-tsを使用する必要があります。
immutableエンティティの使用
多くのエンティティは、オンチェーンデータを表すため、イミュータブル(immutable)となっています。サブグラフの作成者は、サブグラフのGraphQLスキーマの@entityアノテーションを@entity(immutable: true)に変更することによって、一度作成したエンティティを一切変更しないことをシステムに指示することが可能です。
例えばTransferエンティティの場合、スキーマは以下のようになります:
type Transfer @entity(immutable: true) {
id ID!
from Bytes!
to Bytes!
amount BigDecimal
}
エンティティタイプを immutable とマークすると、graph-nodeは通常のmutableなエンティティタイプに必要なものよりも、遥かに安価に構築・維持できるデータベースインデックスを使用できるようになります。
もちろん、不変のエンティティを変更しようとすると、インデックス作成エラーが発生します。

バイトをidとして使用する
多くのサブグラフでは、アドレスのようなバイナリデータをエンティティのidとして使用します。これまでのgraph-nodeでは、idフィールドの型としてID(Stringの同義語)しか許可されていませんでした。バイト列を文字列に変換してidとして使用する場合、文字列はバイナリデータを格納するためにバイト列の2倍の容量を必要とし、UTF-8文字列の比較はロケールを考慮する必要があり、バイト列の比較に使用するバイト単位の比較よりはるかに高価になります。
エンティティのidフィールドの型としてBytesを使用できるようになり、可能な限りBytesを使用することが推奨されます。トークンネームのような人間が読めるテキストを含む属性にはStringを使用することをお勧めします。サブグラフの作成者は、上記の例を使用して、id属性の型定義を簡単に変更することができます:
type Transfer @entity(immutable: true) {
id Bytes!
from Bytes!
to Bytes!
amount BigDecimal
}
さらに、いくつかのコードの変更が必要になります。最も明確な変更として、多くのtoHexString()の呼び出しを削除することで、以下のようなコードが使用できるようになります。
transfer.id = event.transaction.hash.toHexString()
このようになります:
transfer.id = event.transaction.hash
idがバイト配列とカウンタの連結であるエンティティについては、文字列idを "${address}-${counter}"と設定するのを、単にカウンタとアドレスを連結するように変更し、以下のコードを作成する必要があります:
let id = event.transaction.hash
.toHexString()
.concat('-')
.concat(BigInt.fromI32(counter).toString())
このようになります:
let id = event.transaction.hash.concatI32(counter)
日次の取引量など、集計データを格納するエンティティの場合、idは通常、日数を含みます。ここでも、バイト文字列をidとして使用することが有効であります。idを決定するには、次のようにする必要があります:
let dayID = event.block.timestamp.toI32() / 86400
let id = Bytes.fromI32(dayID)
最後に、特殊なアドレスを表す定数もバイト列化する必要がある場合があります。このような場合には:
const BEEF_ADDRESS = '0xdead...beef'
このようになります:
const BEEF_ADDRESS = Bytes.fromHexString('0xdead...beef')
Edge & NodeではRustエンジニアを募集しています。
日本からもぜひご応募ください!
Edge & Nodeはソフトウェア開発会社であり、The Graphの初期チームです。私たちは、分散型未来を構築するプロトコルやDappsを作成し、サポートしています。Edge & Nodeのビジョンについては、edgeandnode.comをご覧ください。また、TwitterやLinkedInでフォローしてください。