Range queries are not effective as the first argument, switching to kind, key, created_at index, which also almost invalidates the need for the Replaceable idx and is only kept for the unique key consistency

This commit is contained in:
Vitor Pamplona
2026-01-01 12:51:43 -05:00
parent 8affb2564b
commit aac880c575
3 changed files with 27 additions and 32 deletions
@@ -113,17 +113,16 @@ class ReplaceableTest {
@Test
fun testTriggersIndexUsageKind0() {
val explainer =
db.store.explainQuery(
val sql =
"""
SELECT * FROM event_headers
WHERE
event_headers.kind = 0 AND
event_headers.pubkey = 'aa' AND
event_headers.created_at < 1766686500 AND
((event_headers.kind IN (0, 3)) OR (event_headers.kind >= 10000 AND event_headers.kind < 20000));
""".trimIndent(),
)
event_headers.created_at < 1766686500
""".trimIndent()
val explainer = db.store.explainQuery(sql)
assertEquals(
"""
@@ -131,9 +130,8 @@ class ReplaceableTest {
WHERE
event_headers.kind = 0 AND
event_headers.pubkey = 'aa' AND
event_headers.created_at < 1766686500 AND
((event_headers.kind IN (0, 3)) OR (event_headers.kind >= 10000 AND event_headers.kind < 20000));
└── SEARCH event_headers USING INDEX replaceable_idx (kind=? AND pubkey=?)
event_headers.created_at < 1766686500
└── SEARCH event_headers USING INDEX query_by_kind_pubkey_created (kind=? AND pubkey=? AND created_at<?)
""".trimIndent(),
explainer,
)
@@ -141,17 +139,16 @@ class ReplaceableTest {
@Test
fun testTriggersIndexUsageKind3() {
val explainer =
db.store.explainQuery(
val sql =
"""
SELECT * FROM event_headers
WHERE
event_headers.kind = 3 AND
event_headers.pubkey = 'aa' AND
event_headers.created_at < 1766686500 AND
((event_headers.kind IN (0, 3)) OR (event_headers.kind >= 10000 AND event_headers.kind < 20000));
""".trimIndent(),
)
event_headers.created_at < 1766686500
""".trimIndent()
val explainer = db.store.explainQuery(sql)
assertEquals(
"""
@@ -159,9 +156,8 @@ class ReplaceableTest {
WHERE
event_headers.kind = 3 AND
event_headers.pubkey = 'aa' AND
event_headers.created_at < 1766686500 AND
((event_headers.kind IN (0, 3)) OR (event_headers.kind >= 10000 AND event_headers.kind < 20000));
└── SEARCH event_headers USING INDEX replaceable_idx (kind=? AND pubkey=?)
event_headers.created_at < 1766686500
└── SEARCH event_headers USING INDEX query_by_kind_pubkey_created (kind=? AND pubkey=? AND created_at<?)
""".trimIndent(),
explainer,
)
@@ -69,8 +69,8 @@ class EventIndexesModule(
// queries by limit (latest records), since, until (sync all) alone
db.execSQL("CREATE INDEX query_by_created_at_id ON event_headers (created_at DESC, id)")
// need to check if this is actually needed.
db.execSQL("CREATE INDEX query_by_created_at_kind_key ON event_headers (created_at DESC, kind, pubkey)")
// queries by kind + pubkey, but not d-tag, even if they are replaceables and addressables, by date.
db.execSQL("CREATE INDEX query_by_kind_pubkey_created ON event_headers (kind, pubkey, created_at DESC)")
// makes deletions on the event_header fast
db.execSQL("CREATE INDEX fk_event_tags_header_id ON event_tags (event_header_row_id)")
@@ -48,8 +48,7 @@ class ReplaceableModule : IModule {
WHERE
event_headers.kind = NEW.kind AND
event_headers.pubkey = NEW.pubkey AND
event_headers.created_at < NEW.created_at AND
((event_headers.kind IN (0, 3)) OR (event_headers.kind >= 10000 AND event_headers.kind < 20000));
event_headers.created_at < NEW.created_at;
END;
""".trimIndent(),
)