⚡ 新着:Elysium テストネット onQuicknodeテストネット HyperEVM上のKinetiqのEVMチェーンのエンドポイント
入手する エンドポイントSOC 2 タイプ II 認証取得・ISO 27001
Solana「Read Layerの再構築:Quicknode のインメモリキャッシュの内部」
Quicknode Solana の読み取りレイヤーをメモリ上で再構築しました。getProgramAccounts、getLargestAccountsなどの処理は、標準のAgaveに比べて10倍から1000倍高速に実行されます。

2026年5月5日 — 読了時間13分

Solana 開発者 大量のデータを返すメソッドや、アカウントセット全体をスキャンする必要があるメソッドを使用する際に、問題が発生することがあります。 getProgramAccounts 制限されたり、無効化されたりします。 getLargestAccounts 決して戻ってこない。その根本原因は構造的なものである。Agave RPCノードは書き込みに最適化されたシステムであり、負荷の高い読み取りメソッドのスロットリングは、ポリシーの選択ではなく、やむを得ない措置である。アプリケーションは、ブロックチェーン プロバイダーのインフラストラクチャの制限を回避するためだけに存在するリトライロジック、キャッシュ層、ポーリング間隔によって、結局はこれを補うことになる。
エコシステム全体がこの問題への取り組みを始めている一方で、Quicknode はすでに、Solana のエコシステムが実際に必要としている「読み取りレイヤー」を構築済みです。2年間にわたる反復的な開発、専用に設計されたインメモリアーキテクチャにより、Agaveのデフォルト設定と比較して10倍から1000倍以上の高速化を実現しています。
Quicknode をご利用のお客様は、これらの特典について別途お申し込みいただく必要はありません。エンドポイント では、すでにこれらの特典が提供されています。
Agave RPCノードは、トランザクションの処理、コンセンサスの形成、および台帳の更新を行うために構築されています。これらのノードが管理するアカウントの状態は、そのプロセスの副産物であり、読み取りに最適化されたストレージではありません。クエリプランナーも、ネイティブなセカンダリインデックスも存在せず、読み取りI/Oと書き込みI/Oの分離も行われていません。
ハードウェアのスケールアップではこの問題は解決しません。読み取りクエリとコンセンサス処理は、同じマシン上の同じCPUを競合して使用するため、ハードウェアを増強しても、競合を解消できないまま、バリデータークラスのコスト(768 GBのRAM、高速NVMe、高帯域幅のネットワーク)を負担することになります。
RPCノードを追加すると、問題はさらに深刻化します。ノードが増えると、Solana のゴシップネットワークやタービンネットワークへの負荷が高まり、実際にそれを必要としているバリデーターの状態伝播が遅くなってしまいます。バリデーターアーキテクチャを通じて読み取りレイヤーをスケールアップすると、書き込みレイヤーのパフォーマンスが著しく低下してしまいます。
データページネーションには一貫性のリスクが伴います。ページ間に新しいブロックが挿入されると、レスポンスの基礎となるアカウントの状態が読み取りの途中で変化してしまいます。大規模な結果セットを順次処理しているアプリケーションは、読み取りが完了する前にデータがずれてしまった状態でデータを受け取ることになります。
Quicknode この問題を早期に認識し、読み取りワークロードをバリデータから分離し、専用のインフラストラクチャから処理するようにしました。現在トラフィックを処理しているアーキテクチャは、こうした取り組みの3回目の改良版です。各改良ではデータにさらに近づけるよう、付加価値をもたらさないのに遅延を招く抽象化レイヤーを段階的に取り除いてきました。そして、この取り組みは現在も継続中です。
第1回:リレーショナルデータベース
最初のイテレーションでは、従来のアプローチを採用しました。つまり、アカウントの状態や元帳データをリレーショナルデータベースに取り込み、インデックスを構築し、そこからクエリを実行するというものです。これにより、リソース競合の問題は即座に解決されました。バリデーターはコンセンサスに専念でき、読み取り処理は別のシステムが担当することになりました。 しかし、リレーショナルデータベースには、Solana の規模において無視できないオーバーヘッドが伴います。具体的には、クエリプランニング、行ロック、Write-Ahead Logging(WAL)の管理、autovacuum、そしてディスクベースのストレージに固有のレイテンシなどです。400ミリ秒ごとにブロックを生成するブロックチェーン にとって、読み取りレイテンシの1マイクロ秒ごとに、1日数百万件のリクエスト全体でその影響が累積していきます。Solana のトラフィックが増加するにつれ、ディスクI/Oが次に克服すべきボトルネックとなりました。
第2イテレーション:専用型の高性能データベース
次のイテレーションは、スキーマそのものから始まりました。「equipe 」では、Solana の実際のアクセスパターンに合わせてデータモデルを簡素化・非正規化し、もはや費用対効果が得られなくなったリレーショナルな構造を廃止しました。この再構築により、書き込みが頻繁なデータ取り込みと低遅延のポイント読み取り向けに構築された高性能なNoSQLデータベースへの移行が可能となり、リレーショナルなアプローチに伴うクエリプランニング、行ロック、および書き込み先行処理といったオーバーヘッドを排除することができました。
スループットとレイテンシの両方が著しく改善され、リレーショナルシステムを大規模に運用する際に生じていた運用上の課題(オートバキュームによる処理の停滞、ロック競合の急増、WALの肥大化)は解消されました。
第3イテレーション:完全インメモリアーキテクチャ
次のステップへの動機は異なっていた。ディスクを基盤とするシステムは、どれほど最適化されていても、ある厳しい限界に直面する。すなわち、あらゆる読み取り操作は、最終的にはRAMよりも桁違いに遅い記憶媒体にアクセスすることになるのだ。この限界を乗り越えるためには、読み取りパスそのものがディスクに依存しないものにならなければならなかった。
現在のアーキテクチャでは、読み取りパスからディスクが完全に排除されています。AccountsDBの状態はメモリ上に保持され、by には、Solana の特定のクエリパターンに合わせて特別に設計された手作りのデータ構造がインデックスとして使用されています。クエリプランナーも、Bツリーの探索も、ページキャッシュのミスも存在せず、あらかじめインデックスが作成されたデータへの直接的なメモリアクセスが行われます。
完全なインメモリアーキテクチャへの移行は、単一の目標、すなわち「生の読み取りパフォーマンス」を最適化するために意図的に下された決定でした。
LedgerDB(各スロットのブロック、トランザクション、メタデータの履歴を保存する)のキャッシュは、同じ設計思想を踏襲しつつ、異なるストレージ戦略を採用しています。Solana の台帳は大きすぎてメモリに完全に収まらないため、階層型設計が採用されています。具体的には、チェーンの先端(tip-of-chain)のデータはメモリ内に常駐させ、履歴データは、そのワークロードに合わせて最適化された高性能な分散データベースから提供されます。
Quicknode Solana Cacheは、外部への依存関係を一切持たずに、チェーンの先端にあるすべてのメソッドを提供する、単一の独立したバイナリです。外部データベースにアクセスするのは、過去の台帳クエリのみです。
AccountsDB(すべてのアカウントの現在の状態を格納する)のキャッシュは完全にインメモリで動作しており、その高速性を実現するための設計上の選択は決して偶然の産物ではありません。4つのメカニズムが連携して、読み取りおよび書き込みパスにおける回避可能な遅延要因をすべて排除しています。
チェーンの一歩先へ
データの鮮度はパフォーマンス上の特性であり、読み取りリクエストが到着する前から始まります。 キャッシュはshred-streamデータソースから直接データを取得するため、完全に形成されたブロックを待つ一般的なAgave RPCノードに表示されるよりも200~400ミリ秒早くアカウントの更新情報を受け取ります。これらの更新情報は低遅延の書き込みパス(near のロックフリー設計によるインメモリ書き込み)を通じて取り込まれるため、この先行優位性はエンドツーエンドで維持され、by の取り込みオーバーヘッドによって相殺されることはありません。
その総合的な効果は、ピーク時において測定可能です。本番環境のトラフィック下では、キャッシュの最新の観測可能なスロットは、同等の構成を持つAgave RPCノードよりも一貫して1~2スロット先行しています。取引 システム、MEV、清算エンジン、リアルタイムダッシュボードなど、「現在の状態はどうか」という問いが重要なワークロードにおいて、これは「最新の状態でアクションを起こす」ことと「すでに古くなったデータに基づいてアクションを起こす」こととの違いに他なりません。
カスタムデータ構造
アカウントの検索、トークンの照会、およびプログラムによるアカウントのフィルタリングを支えるインデックスは、by のベンチマークに基づいて選択された低レベルのデータ構造から構築されています。これは最も汎用的な選択ではありませんが、システムが実際に直面するアクセスパターンにおいて最速のパフォーマンスを示したものです。共有状態では、可能な限りロックの使用を最小限に抑え、並行してアクセスする読み取り処理同士が互いに干渉しないようにしています。
ハードウェアに合わせて最適化
このシステムはハードウェアの利用率を徹底的に追求しており、by データ取り込み、インデックス作成、クエリ処理を専用のCPUコアに割り当てることでコンテキストスイッチのオーバーヘッドを最小限に抑え、また、各コンポーネントの固有の割り当てプロファイルに基づいてメモリアロケータを選択することで、負荷がかかった際のメモリ断片化を軽減しています。
事前計算
可能な限り、システムはアカウントの状態が取り込まれる際に、派生ビュー(供給量の集計値、ソート済みのアカウント一覧、フィルタリング済みのプログラムキャッシュなど)を事前に計算して保持します。これにより、CPU負荷がレイテンシに敏感な読み取りパスから、スループット重視の書き込みパスへと移行します。クエリによって計算がトリガーされることは決してありません。クエリは、すでに存在する結果を読み取るだけです。17ミリ秒 getSupply ベンチマークにおける応答は、このメカニズムが実際に機能していることを示しています。つまり、クエリが到着した時点で、集計結果はすでに存在しているのです。
getProgramAccounts 一見単純そうなタスクを実行します。つまり、by が所有するアカウントのうち、これらのフィルタに一致するものをすべて返すというものです。課題は、これを適切にインデックス化することが難しいという点にあります。対象となるプログラムは、展開されている何千ものプログラムのいずれかであり、それぞれが独自のアカウントスキーマを持っています。
フィルターは通常、 memcmp 特定のバイトオフセットでの演算。これらのオフセットは、プログラムの内部データレイアウトが分かっている場合にのみ意味をなす。A memcmp オフセット32の位置は、SPLトークンではある意味を持ちますが、DEXプログラムではまったく異なる意味を持ちます。
これらすべてに通用する万能なインデックス作成戦略など存在しません。インデックス作成 getProgramAccounts 効率的に行うには、各プログラムのアカウントがどのような構造になっているかを理解する必要があります。Quicknode のインデクサーは、2つの戦略を組み合わせてこの課題に対処しています:
ネイティブにインデックス化されたプログラム
トラフィックが多く、仕組みが十分に理解されている少数のプログラムについては、Quicknode は、アカウントの更新に合わせて、専用のネイティブインデックスを継続的に構築・維持しています。これらは、Solana のトラフィックの大部分を占めるプログラムであり、具体的にはSPL Token(レガシー)、SPL Token-2022、およびStakeプログラムです。
アカウントの構成は把握されており、クライアントが使用するフィルタパターンも把握されています。Quicknode 社は、これらの詳細を直接活用できるようインデックスを設計しました。これらのインデックスにより、プログラムが管理するアカウントが数百万件に上っても、クエリは1ミリ秒未満で処理され、そのほとんどをカバーしています。 getProgramAccounts トラフィックが集中してしまうのは、最も人気のある検索クエリがごく少数のプログラムに集中しているためです。
動的インデックス付きプログラム
それ以外のすべて、つまりあらゆるカスタムDeFiプロトコル、先週デプロイされたすべてのプログラム、あらゆるニッチなユースケースについては、インデクサーは動的な戦略を採用しています。 呼び出し元が特定のプログラムに対してフィルターの組み合わせを初めてリクエストすると、キャッシュは自動的にその場で新しいインデックスを作成します。この最初のリクエストは最適化されていない状態で実行されます。インデクサーは応答する前にプログラムのアカウントをスキャンしてインデックスを構築する必要があるため、キャッシュのウォームアップにかかるこの1回限りのコストは呼び出し元が負担することになります。しかし、そのコールドパスでさえ、Agaveよりも高速です。
その後、同じフィルターに対するリクエストはすべて、アカウントの変更に合わせて常に最新の状態に保たれる、ライブで増分更新されるキャッシュから提供されますオンチェーン 。更新情報は、ネイティブにインデックス化されたプログラムを駆動するのとまったく同じストリーミングパイプラインを通じてflow に送信されるため、キャッシュされたビューが実際の状態からずれることはありません。
その時点以降、ペイロードのサイズやプログラムの人気度にかかわらず、レイテンシは実質的に一定となります。10件のアカウントを返すフィルタも、100万件のアカウントを返すフィルタも、処理はすでに完了しているため、応答時間は同程度のオーダーになります。応答は、リクエストごとに再計算されるのではなく、あらかじめ組み立てられたメモリから直接ストリーミングされます。
新しいプログラムは、デプロイされたその日から利用可能になります。スキーマの統合も、手動での設定も、エンジニアのequipe がサポート を追加するのを待つ必要もありません。新しいプログラムに対して最初にクエリを実行したクライアントによってインデックス作成が開始され、それ以降のすべてのクライアントがその恩恵を受けることができます。
ネイティブインデックスは、実環境におけるトラフィックの大部分に対して最高のパフォーマンスを発揮します。動的インデクサーにより、サポートされていないプログラムやフィルタパターンは一切ありません。
p50
プログラム | 勘定科目 | Quicknode キャッシュウォーム時のTTFB | Agave Direct TTFB | Quicknode vs アガベ |
|---|---|---|---|---|
Jupiter v6 | 60 | 0.2ミリ秒 | 2.0 ms | 10倍速い |
Marinade Finance | 1K | 2.5ミリ秒 |
p99
プログラム | 勘定科目 | Quicknode キャッシュウォーム時のTTFB | Agave Direct TTFB | Quicknode vs アガベ |
|---|---|---|---|---|
Jupiter v6 | 60 | 0.3ミリ秒 | 6ミリ秒 | 20倍速い |
Marinade Finance | 1K | 4ミリ秒 |
getProgramAccounts これはAccountsDBにおいて最も困難な問題であるため、独自の最適化戦略が採用されています。それ以外のすべての処理(ポイント検索、集計、トークンクエリ、ブロックおよびスロットのメタデータ)は、同じ設計原則に基づいて同一のインメモリ状態から処理されます。その原則とは、可能な限り事前計算を行うこと、読み取りパスではロックフリーを実現すること、そしてスキャンではなく単一の検索で解決することです。
その結果、主要なメソッドだけでなく、AccountsDBのすべてのメソッドが、並行処理負荷下でもメモリ内処理と同等の速度で実行されます。トラフィックが増加したり、アカウントセットが拡大したりしても、負荷によってパフォーマンスが低下するサポート対象のメソッドは存在しません。
以下の数値は、同じネットワーク上の標準的なAgaveバリデーターとのベンチマーク結果に基づいています。このパフォーマンスの差はアーキテクチャに起因するものであり、ハードウェアの性能が優れていることによるものではありません。
単純なポイント検索の場合は、 getAccountInfo, getBalance、および getTokenAccountBalance,Quicknode のインデクサーは、Agave と同等の 2~4 ミリ秒のパフォーマンスを発揮します。これらのメソッドのホットパスは、単一のインデックス付き読み取りです。応答時間は、by ネットワークの往復時間によって大きく左右され、by アカウントセットに応じてスケールする処理によるものではありません。集計、ソート済みビュー、またはバリデータが維持していないセカンダリインデックスを必要とするメソッドでは、パフォーマンスにばらつきが見られます。
方法 | Quicknode キャッシュ p50 | アガベ p50 | デルタ |
|---|---|---|---|
getTokenLargestAccounts (USDC) | 4ミリ秒 | 97,535ミリ秒 | 24,384倍速い |
getTokenLargestAccounts (BONK) | 4ミリ秒 | 8,463ミリ秒 | 2,116倍速い |
getLargestAccounts |
特に際立つ3つの結果がある:
getTokenLargestAccounts USDCの場合、Agaveでは100秒近くかかります。リクエストがあるたびに、バリデーターはSPLトークンプログラム全体を走査し、by のミントをフィルタリングしてソートし、キャッシュされた結果やソート済みインデックスがない状態で上位20件を返す必要があります。Quicknode のインデクサーは、残高の変化に応じて増分的に更新される、ミントごとのソート済みセットを維持しています。
getLargestAccounts Agave では 5 分以内に完了しません。バリデータは、リクエストがあるたびに、アカウントセット全体に対してソート済みの集計値を最初から再計算します。Quicknode のインデクサーは、これをランニングインデックスとして維持します。
getTokenAccountsByDelegate Agave ではサポートされていません。Quicknode のインデクサーは、これを一桁のミリ秒単位で処理します。
レイテンシの数値は、個々のリクエストの処理速度を示しています。並行処理の状況はこれとは異なりますが、同様に重要です。1つのAgaveが getTokenLargestAccounts クエリの処理に97秒かかり、そのリクエストがサーバースロットを占有することで、その後に続くすべてのクエリが滞ってしまいます。つまり、1つの処理に時間がかかるリクエストが、同時接続しているすべての呼び出し元に対して遅延の急増を引き起こすのです。
Quicknodeのインデクサーにはそのような不具合はありませんmode 。すべてのクエリは事前に構築されたインメモリインデックスから処理されるため、単一のリクエストが長時間実行されて並行トラフィックを阻害することはありません。持続的な負荷下でも、AccountsDBキャッシュは1秒あたり数万件のリクエストを処理しつつ、P50レイテンシを10ミリ秒未満に抑えています。また、スループットはアカウントセットのサイズやクエリの複雑さではなく、by のハードウェア容量によって制限されます。
すべてのメソッドが10ミリ秒未満で処理されるわけではありません。ネイティブにインデックス化されたセット外のプログラムに対する「コールド」リクエストでは、サブスクリプションの確立とフィルタリング済みキャッシュの構築が行われる間、初回呼び出し時に11~40秒の初期化コストがかかります。同じフィルタに対するそれ以降のリクエストはすべて、メモリ内の「ウォーム」キャッシュから提供されます。
大規模なステーク・プログラムのクエリは、中程度の処理範囲を如実に示しています。Marinadeの81,000件のステーク・アカウントは、Quicknode のインデクサーでは約1秒で処理されますが、Agaveでは6.7秒かかります。インデックスの検索自体は高速ですが、その処理量においてレスポンスを組み立て、シリアライズするには、かなりのCPU負荷がかかります。
Raydium V4 規模(約 705,000 アカウント、約 869 MB の JSON)での応答には、別の限界が見られます。最初のバイトが届くまでの時間は 1.5 秒で、完全な配信にはさらに時間がかかります。これは、869 MB のデータを回線を介して転送するという物理的な制約に縛られているためです。by
パフォーマンスの向上は、あらゆる面で劇的です。どのメソッドも、標準のAgaveバリデータに比べて10倍から1000倍高速に実行されます。単一メソッドの負荷テストでは、1つのインスタンスで350,000 getTransaction レイテンシ40ミリ秒未満で毎秒リクエスト数、および120,000 getAccountInfo 1秒あたりのリクエスト数が、P50で20ミリ秒未満。
AccountsDBとLedgerDBのキャッシュを合わせると、本番環境のRPCトラフィックの約95%、およびSolana のJSON-RPC仕様の約90%をカバーしています。
現在の状態は、2年間にわたる反復開発の成果です。これは最終形ではありません。Quicknode によるSolana の読み取りレイヤーへの投資は継続されています。アーキテクチャはさらに高速化され、メソッドのカバー範囲も拡大し続け、開発者 のニーズとインフラが提供する機能とのギャップを埋める取り組みは今後も止まることはありません。
Solana読み取りと書き込みのワークロードは、根本的に異なる課題です。それには、根本的に異なるアーキテクチャが求められます。Quicknode は、Solana のエコシステムが実際に必要とする読み取りレイヤーを、パフォーマンスを一切妥協することなく、2年以上の歳月をかけてゼロから構築しました。このインフラストラクチャへの継続的な改善は、任意で選択できるものではありません。それは、すべてのQuicknode Solana エンドポイント がすでに提供しているものです。
Quicknode で「Solana 」エンドポイント を作成し、まさにこのワークロードのために特別に構築され、継続的に最適化されている読み取り専用レイヤー上で構築を開始してください。
2017年に設立されたQuicknode は、開発者 および企業向けに、機関投資家レベルのブロックチェーン インフラストラクチャを提供しています。99.99%の稼働率と、76以上のチェーンに対応したサポート を備え、チーム は妥協のないオンチェーン アプリケーションの構築とスケーリングを実現します。
最新のエンジニアリングに関する知見、製品の最新情報、Web3のニュースを、メールボックスに直接お届けします。
12ミリ秒
4.8倍速い |
テンソル | 30K | 0.7ミリ秒 | 213ミリ秒 | 約304倍速い |
オルカ・ワールプール | 91K | 約2.0 ms | 3,515 ms | 約1,760倍速い |
フェニックス DEX | 109K | 約2.6ミリ秒 | 783ミリ秒 | 約301倍速い |
Drift Protocol | 273K | 約6.4ミリ秒 | 3,469ミリ秒 | 約542倍速い |
SPLネームサービス | 341K | 約8.7ミリ秒 | 6,764ミリ秒 | 約777倍速い |
Pump.fun | 507K | 約15ミリ秒 | 27,958ミリ秒 | 約1,864倍速い |
Raydium V4 | 705K | 約18.5ミリ秒 | 10,224 ms | 約553倍速い |
15ミリ秒
3.8倍速い |
テンソル | 30K | 1.2ミリ秒 | 234ミリ秒 | 約195倍速い |
オルカ・ワールプール | 91K | 約2.3ミリ秒 | 3,668 ミリ秒 | 約1,595倍速い |
フェニックス DEX | 109K | 約2.8 ms | 845ミリ秒 | 約302倍速い |
Drift Protocol | 273K | 約7.0 ms | 3,720 ms | 約531倍速い |
SPLネームサービス | 341K | 約8.9ミリ秒 | 7,571ミリ秒 | 約851倍速い |
Pump.fun | 507K | 約16ミリ秒 | 29,718 ms | 約1,857倍高速 |
Raydium V4 | 705K | 約20ミリ秒 | 11,120 ms | 約556倍速い |
7ミリ秒
>300,000 ms(タイムアウト) |
>42,857倍速い |
getSupply | 17ミリ秒 | 6,231ミリ秒 | 367倍速い |
getTokenAccountsByDelegate | 4ミリ秒 | サポート対象外(エラー) | Agaveではこれに対応できません |
getProgramAccounts: Token-2022by 所有者 | 8ミリ秒 | >15,000 ms | 約1,875倍速い |
getProgramAccounts: Orca Whirlpool(91,000アカウント)(ウォーム) | 167ミリ秒 | 3,515 ms | 21倍速い |
getProgramAccounts: Pump.fun (507K アカウント) (ウォーム) | 795ミリ秒 | 27,958ミリ秒 | 35倍速い |