Boas Práticas de Subgraph 3 - Como Melhorar o Desempenho da Indexação e de Queries com Entidades Imutáveis e Bytes como IDs
Reading time: 4 min
Usar Entidades Imutáveis e Bytes como IDs no nosso arquivo schema.graphql
a indexação e o desempenho das queries.
Para fazer uma entidade imutável, basta adicionar (immutable: true)
a uma entidade.
type Transfer @entity(immutable: true) {id: Bytes!from: Bytes!to: Bytes!value: BigInt!}
Ao tornar a entidade Transfer
imutável, o graph-node pode processá-la com mais eficácia, o que melhora as velocidades de indexação e a capacidade de resposta das queries.
Estruturas de Entidades Imutáveis não mudarão no futuro. Uma entidade ideal para se tornar Imutável seria uma que grava diretamente dados de eventos on-chain; por exemplo, um evento Transfer
gravado como uma entidade Transfer
.
Entidades mutáveis tem um block range
(alcance de bloco) que indica a sua validade. Atualizar estas entidades exige que o graph-node ajuste o alcance de bloco de versões anteriores, o que aumenta a carga de trabalho do banco de dados. Queries também precisam de filtragem para encontrar apenas entidades vivas. Entidades imutáveis são mais rápidas por serem todas vivas, e como não mudam, nenhuma verificação ou atualização é necessária durante a escrita, e nenhuma filtragem é necessária durante queries.
Se tiver um campo como status
que precise ser gradualmente modificado, então esta entidade não deve ser imutável. Fora isto, é recomendado usar entidades imutáveis sempre que possível.
Toda entidade requer uma ID. No exemplo anterior, vemos que a ID já é do tipo Bytes.
type Transfer @entity(immutable: true) {id: Bytes!from: Bytes!to: Bytes!value: BigInt!}
Enquanto outros tipos de IDs são possíveis, como String e Int8, recomendamos usar o tipo Bytes para todas as IDs porque strings de caracteres ocupam o dobro do espaço ocupado por strings de Byte para armazenar dados, e comparações de strings de caracteres em UTF-8 devem levar em conta o local, que é muito mais caro que a comparação em byte usada para comparar strings em Byte.
- Se IDs de entidade devem ser legíveis para humanos, como IDs numéricas automaticamente incrementadas ou strings legíveis, então Bytes como IDs não devem ser usados.
- Em caso de integração dos dados de um subgraph com outro modelo de dados que não usa Bytes como IDs, então Bytes como IDs não devem ser usados.
- Melhorias no desempenho de indexação e queries não são desejáveis.
É comum em vários subgraphs usar a concatenação de strings para combinar duas propriedades de um evento em uma ID única, como o uso de event.transaction.hash.toHex() + "-" + event.logIndex.toString()
. Mas como isto retorna um string, isto impede muito o desempenho da indexação e queries de subgraphs.
Em vez disto, devemos usar o método concatI32()
para concatenar propriedades de evento. Esta estratégia resulta numa ID Bytes
que tem um desempenho muito melhor.
export function handleTransfer(event: TransferEvent): void {let entity = new Transfer(event.transaction.hash.concatI32(event.logIndex.toI32()))entity.from = event.params.fromentity.to = event.params.toentity.value = event.params.valueentity.blockNumber = event.block.numberentity.blockTimestamp = event.block.timestampentity.transactionHash = event.transaction.hashentity.save()}
A organização com Bytes como IDs não é o melhor recurso, como visto neste exemplo de query e resposta.
Query:
{transfers(first: 3, orderBy: id) {idfromtovalue}}
Resposta de query:
{"data": {"transfers": [{"id": "0x00010000","from": "0xabcd...","to": "0x1234...","value": "256"},{"id": "0x00020000","from": "0xefgh...","to": "0x5678...","value": "512"},{"id": "0x01000000","from": "0xijkl...","to": "0x9abc...","value": "1"}]}}
As IDs são retornadas como hex.
Para melhorar a organização, devemos criar outro campo na entidade que seja um BigInt.
type Transfer @entity {id: Bytes!from: Bytes! # addressto: Bytes! # addressvalue: BigInt! # unit256tokenId: BigInt! # uint256}
Isto otimizará sequencialmente a organização.
Query:
{transfers(first: 3, orderBy: tokenId) {idtokenId}}
Resposta de query:
{"data": {"transfers": [{"id": "0x…","tokenId": "1"},{"id": "0x…","tokenId": "2"},{"id": "0x…","tokenId": "3"}]}}
É comprovado que usar Entidades Imutáveis e Bytes como IDs aumenta muito a eficiência de subgraphs. Especificamente, segundo testes, houve um aumento de até 28% no desempenho de queries e uma aceleração de até 48% em velocidades de indexação.
Leia mais sobre o uso de Entidades Imutáveis e Bytes como IDs nesta publicação por David Lutterkort, Engenheiro de Software na Edge & Node: .