4 минуты
Лучшие практики субграфов №5 — Упрощение и оптимизация с помощью временных рядов и агрегаций
Краткое содержание
Leveraging the new time-series and aggregations feature in Subgraphs can significantly enhance both indexing speed and query performance.
Обзор
Временные ряды и агрегации снижают накладные расходы на обработку данных и ускоряют запросы, перенося вычисления агрегаций на базу данных и упрощая код отображений. Этот подход особенно эффективен при обработке больших объемов данных, основанных на времени.
Преимущества временных рядов и агрегаций
- Улучшенное время индексирования
- Меньше данных для загрузки: мэппинги обрабатывают меньше данных, поскольку необработанные данные хранятся в виде неизменяемых объектов временных рядов.
- Агрегации, управляемые базой данных: агрегации вычисляются автоматически базой данных, что снижает нагрузку на мэппинги.
- Упрощённый код мэппинга
- Отсутствие ручных вычислений: разработчикам больше не нужно писать сложную логику агрегации в мэппингах.
- Снижение сложности: упрощает обслуживание кода и минимизирует вероятность ошибок.
- Существенное ускорение запросов
- Неизменяемые данные: все данные временных рядов неизменяемы, что обеспечивает эффективное хранение и извлечение.
- Эффективное разделение данных: агрегаты хранятся отдельно от необработанных данных временных рядов, что позволяет запросам обрабатывать значительно меньше данных — часто на несколько порядков меньше.
Важные замечания
- Незаменяемость данных: данные временных рядов не могут быть изменены после записи, что обеспечивает целостность данных и упрощает индексирование.
- Автоматическое управление ID и метками времени: поля id и timestamp автоматически управляются graph-node, что снижает вероятность ошибок.
- Эффективное хранение данных: разделение необработанных данных и агрегатов оптимизирует хранилище и ускоряет выполнение запросов.
Как внедрить временные ряды и агрегации
Предварительные требования
You need spec version 1.1.0
for this feature.
Определение объектов временных рядов
Объект временного ряда представляет собой необработанные данные, собранные с течением времени. Он определяется с помощью аннотации @entity(timeseries: true)
. Ключевые требования:
- Неизменяемость: объекты временного ряда всегда неизменяемы.
- Обязательные поля:
id
: должен быть типаInt8!
и автоматически увеличиваться.timestamp
: должен быть типаTimestamp!
и автоматически устанавливаться в соответствии с временной меткой блока.
Пример:
1type Data @entity(timeseries: true) {2 id: Int8!3 timestamp: Timestamp!4 amount: BigDecimal!5}
Определение объектов агрегаций
Объект агрегации вычисляет агрегированные значения из источника данных временного ряда. Он определяется с помощью аннотации @aggregation
. Ключевые компоненты:
- Аргументы аннотации:
intervals
: указывает временные интервалы (например,["hour", "day"]
).
Пример:
1type Stats @aggregation(intervals: ["hour", "day"], source: "Data") {2 id: Int8!3 timestamp: Timestamp!4 sum: BigDecimal! @aggregate(fn: "sum", arg: "amount")5}
In this example, Stats aggregates the amount field from Data over hourly and daily intervals, computing the sum.
Запрос агрегированных данных
Агрегации предоставляются через поля запросов, которые позволяют фильтровать и извлекать данные на основе измерений и временных интервалов.
Пример:
1{2 tokenStats(3 interval: "hour"4 where: { token: "0x1234567890abcdef", timestamp_gte: "1704164640000000", timestamp_lt: "1704251040000000" }5 ) {6 id7 timestamp8 token {9 id10 }11 totalVolume12 priceUSD13 count14 }15}
Использование измерений в агрегациях
Измерения — это неагрегированные поля, которые используются для группировки точек данных. Они позволяют выполнять агрегации на основе определённых критериев, таких как токен в финансовом приложении.
Пример:
Объект временного ряда
1type TokenData @entity(timeseries: true) {2 id: Int8!3 timestamp: Timestamp!4 token: Token!5 amount: BigDecimal!6 priceUSD: BigDecimal!7}
Объект агрегации с измерением
1type TokenStats @aggregation(intervals: ["hour", "day"], source: "TokenData") {2 id: Int8!3 timestamp: Timestamp!4 token: Token!5 totalVolume: BigDecimal! @aggregate(fn: "sum", arg: "amount")6 priceUSD: BigDecimal! @aggregate(fn: "last", arg: "priceUSD")7 count: Int8! @aggregate(fn: "count", cumulative: true)8}
- Поле измерения:
token
группирует данные, так что агрегированные значения вычисляются для каждого токена. - Агрегаты:
- totalVolume: сумма количества.
- priceUSD: последняя зафиксированная цена в USD.
- count: кумулятивное количество записей.
Функции агрегации и выражения
Поддерживаемые функции агрегации:
- sum
- count
- min
- max
- first
- last
Аргумент в @aggregate
может быть
- Названием поля из объекта временных рядов.
- Выражением, использующим поля и константы.
Примеры выражений агрегации
- Сумма стоимости токена: @aggregate(fn: “sum”, arg: “priceUSD * amount”)
- Максимальное положительное значение суммы: @aggregate(fn: “max”, arg: “greatest(amount0, amount1, 0)”)
- Условная сумма: @aggregate(fn: “sum”, arg: “case when amount0 > amount1 then amount0 else 0 end”)
Поддерживаемые операторы и функции включают базовую арифметику (+, -, *, /), операторы сравнения, логические операторы (and, or, not), а также SQL-функции, такие как greatest, least, coalesce и другие.
Параметры запроса
- interval: указывает временной интервал (например, “час”).
- where: фильтрует данные по измерениям и диапазонам временных меток.
- timestamp_gte / timestamp_lt: фильтрует по времени начала и окончания (микросекунды с эпохи).
Примечания
- Сортировка: результаты автоматически сортируются по временным меткам и идентификатору в порядке убывания.
- Текущие данные: опциональный текущий аргумент может включать текущий, частично заполненный интервал.
Заключение
Implementing timeseries and aggregations in Subgraphs is a best practice for projects dealing with time-based data. This approach:
- Улучшает производительность: ускоряет индексирование и запросы, снижая нагрузку на обработку данных.
- Упрощает разработку: устраняет необходимость в ручном написании логики агрегации в мэппингах.
- Эффективно масштабируется: обрабатывает большие объемы данных, не ухудшая скорость и отзывчивость.
By adopting this pattern, developers can build more efficient and scalable Subgraphs, providing faster and more reliable data access to end-users. To learn more about implementing timeseries and aggregations, refer to the Timeseries and Aggregations Readme and consider experimenting with this feature in your Subgraphs.