mirror of
https://github.com/block/buzz.git
synced 2026-10-31 14:31:02 +00:00
perf(db): index thread reply keyset pagination
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co> Signed-off-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co> Co-authored-by: coder 0 <d97ebdbb198c7237c94f84ea8bb8a73583ea067407eebd0062abbb3962527fb1@buzz.block.builderlab.xyz> Signed-off-by: coder 0 <d97ebdbb198c7237c94f84ea8bb8a73583ea067407eebd0062abbb3962527fb1@buzz.block.builderlab.xyz>
This commit is contained in:
committed by
coder 0
parent
17d2147eca
commit
173b2d21dd
@@ -625,7 +625,7 @@ mod tests {
|
||||
let mut migrations: Vec<_> = MIGRATOR.iter().collect();
|
||||
migrations.sort_by_key(|migration| migration.version);
|
||||
|
||||
assert_eq!(migrations.len(), 31);
|
||||
assert_eq!(migrations.len(), 32);
|
||||
assert_eq!(migrations[0].version, 1);
|
||||
assert_eq!(&*migrations[0].description, "initial schema");
|
||||
assert!(migrations[0]
|
||||
@@ -1057,6 +1057,25 @@ mod tests {
|
||||
.as_str()
|
||||
.contains("error_code"));
|
||||
assert!(include_str!("../../../schema/schema.sql").contains("error_code TEXT"));
|
||||
|
||||
// Thread subtree pagination uses the full tenant/root/keyset tuple. Keep
|
||||
// the covering index additive so brownfield migration checksums remain
|
||||
// stable.
|
||||
assert_eq!(migrations[31].version, 32);
|
||||
assert!(migrations[31]
|
||||
.sql
|
||||
.as_str()
|
||||
.contains("CREATE INDEX IF NOT EXISTS idx_thread_metadata_root_keyset"));
|
||||
assert!(migrations[31]
|
||||
.sql
|
||||
.as_str()
|
||||
.contains("(community_id, root_event_id, event_created_at, event_id)"));
|
||||
assert!(!migrations[0]
|
||||
.sql
|
||||
.as_str()
|
||||
.contains("idx_thread_metadata_root_keyset"));
|
||||
assert!(include_str!("../../../schema/schema.sql")
|
||||
.contains("CREATE INDEX idx_thread_metadata_root_keyset"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
21
migrations/0032_thread_metadata_keyset_index.sql
Normal file
21
migrations/0032_thread_metadata_keyset_index.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- ── Thread reply keyset pagination index ─────────────────────────────────────
|
||||
-- Thread subtree reads filter by tenant and root, then page in ascending
|
||||
-- (event_created_at, event_id) order. Include the keyset columns so PostgreSQL
|
||||
-- can satisfy both the filter and ordering from one index scan.
|
||||
--
|
||||
-- Lock note: built without CONCURRENTLY because sqlx runs each migration inside
|
||||
-- a transaction and CREATE INDEX CONCURRENTLY cannot run in one. This takes a
|
||||
-- SHARE lock on `thread_metadata` (blocking writes, not reads) for the duration
|
||||
-- of the build. `thread_metadata` is on the event insertion path and may be
|
||||
-- large on brownfield databases, so operators should pre-build it by hand before
|
||||
-- deploying this migration:
|
||||
--
|
||||
-- CREATE INDEX CONCURRENTLY idx_thread_metadata_root_keyset
|
||||
-- ON thread_metadata (community_id, root_event_id, event_created_at, event_id);
|
||||
--
|
||||
-- IF NOT EXISTS then makes this migration a no-op on that database.
|
||||
--
|
||||
-- Additive migration: previously applied files must not change checksum.
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_thread_metadata_root_keyset
|
||||
ON thread_metadata (community_id, root_event_id, event_created_at, event_id);
|
||||
@@ -531,6 +531,8 @@ CREATE TABLE thread_metadata (
|
||||
|
||||
CREATE INDEX idx_thread_metadata_parent ON thread_metadata (community_id, parent_event_id);
|
||||
CREATE INDEX idx_thread_metadata_root ON thread_metadata (community_id, root_event_id);
|
||||
CREATE INDEX idx_thread_metadata_root_keyset
|
||||
ON thread_metadata (community_id, root_event_id, event_created_at, event_id);
|
||||
CREATE INDEX idx_thread_metadata_channel_depth
|
||||
ON thread_metadata (community_id, channel_id, depth, event_created_at);
|
||||
CREATE INDEX idx_thread_metadata_event_id ON thread_metadata (community_id, event_id);
|
||||
|
||||
Reference in New Issue
Block a user