Почему разработка subgraph тормозит при росте данных
Разработка subgraph на первый взгляд — это декларативная схема: сущности, обработчики событий, отображение полей. Обработчик ловит событие контракта, пишет сущность, а клиент читает готовую выборку вместо обхода логов через запросы к данным смарт-контракта напрямую. Пока событий десятки в сутки, схема выглядит идеальной — узкое место спрятано в слое данных.
Оно проявляется, когда частота событий в сети растёт: транзакций на адрес становится больше, каждый блок несёт пачку логов, и обработчики перестают успевать за головами цепи. Отставание индексации накапливается нелинейно: очередь растёт быстрее, чем пропускная способность записи, а любая правка схемы или отображения требует переиндексации с нуля — часы и сутки простоя на исторических контрактах. Индексация блокчейн-данных перестаёт быть фоновым процессом и становится критическим путём.
Цена — искажённая картина на витрине. Интерфейс показывает баланс по неполному набору событий, отчёт строится по срезу, который отстал на тысячи блоков, сверка с состоянием цепи даёт расхождения. Хуже, что расхождение тихое: данные валидны по форме, просто неполны, и обнаруживается это при разборе инцидента, а не на графике.
Дальше разбираем, как это закрывается: разделением потока на горячие и архивные сущности, фильтрами по адресам контрактов, пакетной записью и контрольными точками, по которым видно фактическое отставание, а не только статус последнего блока.
Что даёт управляемый слой индексации: эффект в цифрах
Разработка subgraph в The Graph даёт измеримый эффект не сама по себе, а через управляемый слой индексации: схема, сопоставления событий и правила переиндексации описаны в манифесте и версионируются вместе с контрактами. Данные собираются заранее, поэтому запрос приложения больше не ждёт обхода сети.
Скорость сборки данных перестаёт зависеть от объёма истории: полная переиндексация укладывается в минуты, а новые события обрабатываются непрерывно по мере поступления. Свежесть ответа измеряется задержкой между событием в сети и записью в индексе и держится в пределах секунд.
Время восстановления после сбоя сокращается: индекс поднимается из сохранённых контрольных точек, а не пересобирается с нуля, поэтому ручная сверка не нужна. Уходит целый класс отказов — рассинхронизация данных приложения с состоянием контрактов, пропущенные события при реорганизации цепочки, дубли после повторной обработки.
Нагрузка на запросы распределяется: повторяющиеся выборки отдаёт кэш, тяжёлые агрегаты считаются один раз при индексации, а не на каждый вызов. Доля устаревших ответов падает до нуля, потому что приложение читает согласованное состояние на конкретный момент, а не промежуточный результат обхода.
Метрики — скорость сборки, задержка ответа, доля восстановлений без ручного вмешательства — выводим в мониторинг, чтобы деградация была видна до жалоб пользователей. Пороговые значения фиксируем в регламенте эксплуатации, а не в переписке.
Подходы к разработке subgraph: сравнение вариантов
Сравнение подходов к разработке subgraph упирается в две вещи: насколько нестандартна логика контрактов и кто отвечает за индекс после запуска. Все три варианта реализации дают рабочий индекс на The Graph, но по-разному переживают обновление контракта, смену формата событий и рост числа запросов от внешних потребителей данных.
Типовая схема покрывает стандартные сущности — токены, переводы, балансы — и разворачивается быстро, если в проекте нет кастомной логики. Самостоятельная сборка внутри команды даёт полный контроль над запросами, но держится на одном инженере, который помнит обработчики событий и их порядок. Заказная схема проектируется под конкретную модель данных и остаётся рабочей, когда контракты меняются.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Самостоятельная сборка внутри команды | Логика контрактов простая, есть инженер, знающий схему событий | Зависит от одного человека, задержки при изменении контракта, нет ревью запросов |
| Типовая схема по шаблону | Стандартные токены, переводы, балансы, нужен быстрый старт | Не покрывает кастомные сущности, при доработке расходится с реальной моделью |
| Заказная схема с сопровождением | Нестандартная логика, несколько контрактов, внешние потребители | Дольше проектирование, нужны доступы к репозиториям и описание событий |
Переход между вариантами не требует остановки сервиса: новая версия индексируется параллельно со старой, потребители переводятся на неё после сверки сумм и количеств. Поэтому подход выбирают не «навсегда», а под текущий этап — сравнение подходов фиксирует, что именно меняется при переходе.
Как мы ведём внедрение: этапы инженерной работы
Этапы внедрения построены так, чтобы каждый заканчивался проверяемым результатом, а не отчётом о затраченных часах. Порядок одинаков и для нового сабграфа, и для перевода уже работающей индексации на нашу поддержку — меняется только глубина разбора на первом шаге.
-
Разбор контрактов и доступов. Собираем адреса, интерфейсы и перечень событий, сверяем их с фактическим состоянием сети. Отдельно фиксируем, кто владеет ключами развёртывания и есть ли доступ к историческим данным: без архива блоков индексация с нуля упирается в первый же этап.
-
Разбор схемы данных. Определяем сущности, поля и связи от реальных выборок — что запрашивает интерфейс, что нужно аналитике. Неиспользуемые поля раздувают хранилище и замедляют ответы, поэтому схему согласуем до написания обработчиков.
-
Проектирование обработчиков. Каждое событие превращается в изменение сущностей с учётом порядка блоков, реорганизаций и повторных вызовов. Создание записей по требованию закладываем сразу, чтобы не терять данные при первом обращении.
-
Настройка индексации. Задаём сеть, стартовый блок, отсечение ненужных диапазонов и пакетную запись. Прогоняем полную синхронизацию на тестовом контуре и замеряем время до актуального блока.
-
Проверка корректности выборок. Сверяем ответы по контрольным адресам с данными напрямую из сети: балансы, объёмы, число событий. Расхождения устраняем до выкладки, а не после жалобы пользователя.
-
Деплой и версионирование. Публикуем с явной версией — предыдущая остаётся доступной для отката и клиентов, которые ещё не обновились.
-
Передача проекта. Отдаём схему, конфигурацию, инструкции по обновлению и доступам: команда сопровождает индексацию без нашего участия.
Артефакты передачи: схемы, регламенты, документация
Передаём не только работающий индекс, но и всё для его самостоятельного сопровождения. Проверка простая: ваш инженер вносит правку в обработку события и выпускает новую версию, не задавая нам вопросов. В комплект входят:
- Документация по схеме: сущности, поля и связи, соответствие событиям контракта, индексы — с пометкой, что придётся править при добавлении нового события.
- Описание сущностей и полей: назначение атрибута, тип, источник в логах контракта, поведение при пропущенных значениях.
- Правила обработки событий: что индексируется, как разводятся повторы, реорганизации цепочки и обновление контракта.
- Политики доступа: роли в панели управления, отдельные ключи для ручного деплоя и для сборки, порядок ротации.
- Регламент сопровождения: порядок выпуска версии, сверка индекса с состоянием контракта, реакция на расхождения.
- Инструкции для команды: локальный запуск узла и индексатора, типовые запросы, воспроизведение сбоя на диапазоне блоков.
- Порядок обновления и откат: как закрепить предыдущую версию, чтобы запросы не падали, пока новая досчитывает историю.
Каждый пункт защищается на приёмке: развёртывание и выпуск версии воспроизводим по инструкции без участия автора. Сопровождение остаётся у вашей команды, а мы подключаемся только по новым задачам.
Кейс: убрали отставание индексации и класс отказов
На входе — рабочий subgraph на The Graph: основной контракт и фабрика как источники событий. Запросы отдавались, но аналитические панели отставали от сети на 6-9 часов, а каждая реорганизация цепочки запускала полную переиндексацию.
Где было узкое место
Обработчики читали состояние контракта в момент обработки, а не брали его из самого события: на каждый блок уходило несколько сетевых обращений, и обработка не успевала за головой цепочки. Вторым ограничением стала запись — сущности сохранялись по одной на событие, поэтому хранилище держало скорость.
Отдельный класс отказов — отсутствие контроля финальности. События из неподтверждённых блоков попадали в базу, и после реорганизаций расхождения приходилось разбирать вручную, сверяя агрегаты с состоянием контракта.
Что изменили и что зафиксировали на замерах
Маппинги переписали: данные берём из события, внешние обращения вынесли из горячего пути в пакетную обработку. Сущности собираются пачкой и сохраняются за один проход, неизменяемые поля вынесены в отдельный тип, схема почищена от дублей. До записи добавлен порог подтверждений, при реорганизации обработка перезапускается с высоты форка.
После переезда отставание индексации измеряется секундами вместо часов, полная переиндексация — три часа вместо сорока с лишним, объём хранилища сократился примерно втрое. Аналитическая панель отвечает на порядок быстрее, а за квартал наблюдений — ни одной рассинхронизации после реорганизаций; раньше это были еженедельные инциденты.
Что делать, если свой сборщик данных уже развёрнут?
Свой сборщик не обязательно выключать, чтобы перейти на The Graph: новый контур поднимается рядом, а потребители переключаются по одному. Решает не сравнение инструментов, а число читателей данных и требования к их свежести — от этого зависит, нужна параллельная работа двух контуров или хватит полной замены.
Главная сложность — миграция данных. Историю нельзя перенести выгрузкой таблиц: каждую запись нужно воспроизвести из событий контракта, иначе агрегаты разойдутся с цепочкой. Сверяем контуры по диапазонам блоков — число событий на контракт, суммы по токенам, последнее состояние адреса: расхождение в конкретном диапазоне показывает, где индексация потеряла блок.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Полная замена | Один потребитель, простой допустим | Переиндексация истории занимает часы, нужна точка отсечения по номеру блока |
| Постепенный переход | Несколько потребителей, разные схемы чтения | Долгий период двойной записи и регулярная сверка расхождений |
| Параллельная работа | Критичный контур нельзя останавливать | Двойная нагрузка на узлы, нужна дедупликация записей |
Совместимость контуров держится на одинаковых идентификаторах: хеш транзакции и индекс лога, идемпотентная запись, единый формат адресов и сумм. Тогда повторный проход не плодит дубли, а потребителя можно вернуть на свой сборщик без потери истории.
Путь выбираем по критичности контура: где простой допустим — идём полной заменой, где нет — параллельной работой с постепенным переходом потребителей.
Свежесть данных, доступы и ограничения: частые сомнения
Сомнения на этапе выбора подрядчика обычно одни и те же: насколько быстро индекс догоняет новые блоки, кто именно получит доступ к запросам, что произойдёт при резком росте нагрузки и как больно менять схему после запуска. Ниже — короткие ответы по каждому пункту, без маркетинга и общих слов.
Насколько свежие данные отдаёт subgraph?
Индексатор обрабатывает блоки по мере подтверждения и опирается на настраиваемую глубину финализации — она определяет компромисс между скоростью отдачи и устойчивостью к реорганизациям цепи. Отставание контролируем сверкой с независимым узлом: если расхождение выходит за заданный порог, срабатывает оповещение, а не тихое устаревание цифр в интерфейсе.
Как разграничивается доступ к данным?
Доступ выдаём ключами: отдельный ключ на команду или сервис, свои лимиты частоты и объёма выборки, журнал обращений. Ключ отзывается без пересборки схемы, поэтому вывод подрядчика или внутреннего потребителя не требует остановки сервиса и повторного развёртывания.
Что будет при росте числа запросов?
Ограничения снимаются архитектурно: пагинация вместо сплошной выгрузки, заранее посчитанные агрегаты в схеме вместо тяжёлых обходов истории, кэширование повторяющихся выборок. Когда одного индексатора перестаёт хватать, добавляется второй — потребители этого не замечают.
Как обновляется схема без простоя?
Новая версия subgraph разворачивается параллельно со старой. Потребители мигрируют постепенно, старая версия остаётся доступной до последнего клиента, откат — это переключение указателя на предыдущую сборку. Так изменение модели данных не превращается в аварию.
Если какое-то из этих сомнений не закрыто — разберём его на вашей схеме: покажем, как индексация, доступы и версионирование лягут на конкретные запросы.Обсудим задачу: что уточним и как вернёмся с планом
Чтобы оценка проекта была предметной, а не «на глаз», нам нужен набор вводных — по ним видно объём маппингов, число сущностей и глубину индексации. Ниже минимальный список; если чего-то пока нет, подскажем, где это взять и что можно заменить.
- Адреса контрактов и сеть: где разворачивается subgraph и какие ещё окружения нужно поддержать — тестовая сеть или основная.
- ABI или исходники контрактов — по ним сверяем сигнатуры событий и отсекаем расхождения между документом и кодом.
- Перечень событий для индексации и правило, какие из них считаем значимыми: этим задаётся объём обрабатываемых записей.
- Схема сущностей и связей: какие вопросы задают к данным и как их агрегируют — от неё зависит структура хранения и число запросов.
- Типовые выборки, которые пойдут с интерфейса или дашборда: фильтры, сортировки, пагинация, ожидаемое время ответа.
- Блок старта и адреса деплоя — чтобы не тянуть в индекс служебную историю и сохранить воспроизводимость сборки.
- Доступ к узлу и репозиторий со сборкой: нужен, чтобы прогонять индексацию на реальных данных, а не на выборке.
Дальше возвращаемся с оценкой проекта и планом работ: этапы, состав команды, что делаем мы и что остаётся на вашей стороне, где точки согласования. Если по вводным видно развилки — например, публичный размещённый subgraph или приватный на своём узле, — покажем оба варианта и их ограничения по нагрузке и доступам. Старт проекта начинается после того, как план и критерии приёмки согласованы.







