4 minutes
Osvědčený postup 3 - Zlepšení indexování a výkonu dotazů pomocí neměnných entit a bytů jako ID
TLDR
Použití neměnných entit a bytů pro ID v našem souboru schema.graphql
výrazně zlepšuje rychlost indexování a výkonnost dotazů.
Nezměnitelné entity
Aby byla entita neměnná, jednoduše k ní přidáme (immutable: true)
.
1type Transfer @entity(immutable: true) {2 id: Bytes!3 from: Bytes!4 to: Bytes!5 value: BigInt!6}
Tím, že je entita Transfer
neměnná, je grafový uzel schopen ji zpracovávat efektivněji, což zvyšuje rychlost indexování a odezvu dotazů.
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 onchain event data, such as a Transfer
event being logged as a Transfer
entity.
Pod kapotou
Mutabilní entity mají “rozsah bloku”, který udává jejich platnost. Aktualizace těchto entit vyžaduje, aby uzel grafu upravil rozsah bloků předchozích verzí, což zvyšuje zatížení databáze. Dotazy je také třeba filtrovat, aby byly nalezeny pouze živé entity. Neměnné entity jsou rychlejší, protože jsou všechny živé, a protože se nebudou měnit, nejsou při zápisu nutné žádné kontroly ani aktualizace a při dotazech není nutné žádné filtrování.
Kdy nepoužívat nezměnitelné entity
Pokud máte pole, jako je status
, které je třeba v průběhu času měnit, neměli byste entitu učinit neměnnou. Jinak byste měli používat neměnné entity, kdykoli je to možné.
Bajty jako IDs
Každá entita vyžaduje ID. V předchozím příkladu vidíme, že ID je již typu Bytes.
1type Transfer @entity(immutable: true) {2 id: Bytes!3 from: Bytes!4 to: Bytes!5 value: BigInt!6}
I když jsou možné i jiné typy ID, například String a Int8, doporučuje se pro všechna ID používat typ Bytes, protože pro uložení binárních dat zabírají znakové řetězce dvakrát více místa než řetězce Byte a při porovnávání znakových řetězců UTF-8 se musí brát v úvahu locale, což je mnohem dražší než bytewise porovnávání používané pro porovnávání řetězců Byte.
Důvody, proč nepoužívat bajty jako IDs
- Pokud musí být IDs entit čitelné pro člověka, například automaticky doplňované číselné IDs nebo čitelné řetězce, neměly by být použity bajty pro IDs.
- If integrating a Subgraph’s data with another data model that does not use Bytes as IDs, Bytes as IDs should not be used.
- Zlepšení výkonu indexování a dotazování není žádoucí.
Konkatenace s byty jako IDs
It is a common practice in many Subgraphs to use string concatenation to combine two properties of an event into a single ID, such as using event.transaction.hash.toHex() + "-" + event.logIndex.toString()
. However, as this returns a string, this significantly impedes Subgraph indexing and querying performance.
Místo toho bychom měli použít metodu concatI32()
pro spojování vlastností událostí. Výsledkem této strategie je ID Bytes
, které je mnohem výkonnější.
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}
Třídění s bajty jako ID
Třídění pomocí bajtů jako IDs není optimální, jak je vidět v tomto příkladu dotazu a odpovědi.
Dotaz:
1{2 transfers(first: 3, orderBy: id) {3 id4 from5 to6 value7 }8}
Odpověď na dotaz:
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 jsou vrácena v hex.
Abychom zlepšili třídění, měli bychom v entitě vytvořit další pole, které bude BigInt.
1type Transfer @entity {2 id: Bytes!3 from: Bytes! # address4 to: Bytes! # address5 value: BigInt! # unit2566 tokenId: BigInt! # uint2567}
To umožní postupnou optimalizaci třídění.
Dotaz:
1{2 transfers(first: 3, orderBy: tokenId) {3 id4 tokenId5 }6}
Odpověď na dotaz:
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}
Závěr
Using both Immutable Entities and Bytes as IDs has been shown to markedly improve Subgraph efficiency. Specifically, tests have highlighted up to a 28% increase in query performance and up to a 48% acceleration in indexing speeds.
Více informací o používání nezměnitelných entit a bytů jako ID najdete v tomto příspěvku na blogu Davida Lutterkorta, softwarového inženýra ve společnosti Edge & Node: Dvě jednoduchá vylepšení výkonu podgrafu.