Repository navigation
logdb: evaluate narrow topic0-only event filters by seq range scan - #1693
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
8fcc686 to
b9a2f55
Compare
|
While I read this PR, I wondered about a few edge cases, so I did some tests. What if the request has no What about other criteria without an address? Do mixed criteria sets get slower? How slow is a topic0 with few events? Can you run these on your mainnet
|
|
I don't think we need to cover every case here. The API already has a timeout. When a user or dApp sends an unreasonable request and it times out, the right answer is for them to narrow the query conditions, or to use a centralized indexing/query service, rather than for the node to optimize every possible query shape. |
…ns (#1694) Co-authored-by: tony <liboliqi@gmail.com>
Description
POST /logs/eventwith a narrow block range and topic0-only criteria (noaddress, notopic1..4) runs in time proportional to the chain-wide count of that topic0, not to the block range. The subquery is planned asSEARCH event USING COVERING INDEX event_i1 (topic0=?)+USE TEMP B-TREE FOR ORDER BY:event_i1is(topic0, address), and withaddressunconstrained theseqbounds cannot enter the index, so every entry for that topic0 is read and filtered. On a mainnetlogs-v2.db(797M events) a single-block Transfer query takes ~110 s regardless of the range.This PR changes only the generated SQL. For a criterion that constrains nothing but
topic0, and only when the requested span is at most 100,000 blocks, the term is rendered as+topic0 = …. The unary plus stops SQLite from using the term for index lookup, so the only remaining constraint is theseqrange (the rowid) and the plan becomesSEARCH event USING INTEGER PRIMARY KEY (rowid>? AND rowid<?): cost proportional to the rows in the span, no sort, earlyLIMITstop. Every other criteria shape, and topic0-only queries over wider spans or with no range, keep their current plan.Measured on the same mainnet DB (external SSD, sqlite3 3.51):
The 100,000-block bound keeps the worst case (rare topic0, cold page cache) an order of magnitude under the 10 s API timeout; at 1,000,000 blocks the same case measured 9.8 s cold. Wider topic0-only queries are unchanged and still slow; fixing those needs an index on
(topic0), which #1690 proposes and which is a separate decision. The plan-pinning test here is the one proposed in #1690's review, with expectations for the current schema, so it carries over if that index lands later.Mixed criteria sets that contain a topic0-only criterion also take the range scan within the bound (SQLite drops the multi-index OR plan once one branch has no indexable term); this is pinned by test.
No linked issue.
Type of change
How Has This Been Tested?
TestEventQueryPlanPerCriteriaShape:EXPLAIN QUERY PLANpinned for 9 criteria shapes × narrow/wide/nil range, plus the 100,000-block boundary on both sidesTestEventFilterScanEquivalence: on a written in-memory DB, the scan path returns exactly the rows and order of the index path for topic0-only filters across ASC/DESC, ranges and offset/limit./logdb/...and./api/...suites;make lintcleanlogs-v2.dbsnapshot opened read-onlyTest Configuration:
Checklist:
https://claude.ai/code/session_01EQzJUxb99n2LVoqvi7ioAx