From 7688e4d3a8024cbf04852969b570da4d2e79bd39 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Wed, 14 May 2025 20:13:14 -0400 Subject: [PATCH] ssb: I tried smarter data structures in my own code, but a better database index shows better performance for determining follows. --- src/ssb.db.c | 24 +++++++++++++----------- src/ssb.tests.c | 11 ++++++++--- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/ssb.db.c b/src/ssb.db.c index fe23d208..11c56b6c 100644 --- a/src/ssb.db.c +++ b/src/ssb.db.c @@ -190,20 +190,21 @@ void tf_ssb_db_init(tf_ssb_t* ssb) _tf_ssb_db_exec(db, "ALTER TABLE messages RENAME COLUMN sequence_before_author TO flags"); } - _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_id_author_index ON messages (id, author)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_sequence_index ON messages (author, sequence)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_author_timestamp_index ON messages (author, timestamp)"); + _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_channel_author_timestamp_root_index ON messages (content ->> 'channel', author, timestamp, content ->> 'root')"); + _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_contact_index ON messages(author, sequence, content ->> '$.contact', content ->> '$.following', content ->> '$.blocking') WHERE content ->> '$.type' = 'contact'"); + _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_id_author_index ON messages (id, author)"); + _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_size_by_author_index ON messages (author, length(content))"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_timestamp_index ON messages (timestamp)"); _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_type_timestamp_index ON messages (content ->> 'type', timestamp)"); - _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_size_by_author_index ON messages (author, length(content))"); - _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_root_timestamp_index "); - _tf_ssb_db_exec(db, "CREATE INDEX IF NOT EXISTS messages_channel_author_timestamp_root_index ON messages (content ->> 'channel', author, timestamp, content ->> 'root')"); - _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_index"); _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_author_id_index"); _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_by_author_index"); - _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_timestamp_author_index"); _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_id_index"); + _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_timestamp_author_index"); + _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_index"); _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_root_rowid_index"); + _tf_ssb_db_exec(db, "DROP INDEX IF EXISTS messages_type_author_channel_root_timestamp_index "); _tf_ssb_db_exec(db, "CREATE TABLE IF NOT EXISTS blobs (" " id TEXT PRIMARY KEY," @@ -1661,12 +1662,13 @@ static void _get_following(sqlite3* db, sqlite3_stmt* statement, following_t* en static sqlite3_stmt* _make_following_statement(sqlite3* db) { sqlite3_stmt* statement = NULL; + if (sqlite3_prepare(db, - "SELECT content ->> '$.contact' AS contact, content ->> '$.following', content ->> '$.blocking' " - "FROM messages " - "WHERE contact IS NOT NULL AND author = ? AND content ->> '$.type' = 'contact' " - "ORDER BY sequence", - -1, &statement, NULL) != SQLITE_OK) + "SELECT content ->> '$.contact' AS contact, content ->> '$.following', content ->> '$.blocking' " + "FROM messages " + "WHERE author = ? AND content ->> '$.type' = 'contact' AND contact IS NOT NULL " + "ORDER BY content ->> '$.contact', sequence", + -1, &statement, NULL) != SQLITE_OK) { tf_printf("prepare failed: %s", sqlite3_errmsg(db)); } diff --git a/src/ssb.tests.c b/src/ssb.tests.c index 622e2f24..0985e3d2 100644 --- a/src/ssb.tests.c +++ b/src/ssb.tests.c @@ -1618,10 +1618,15 @@ void tf_ssb_test_following_perf(const tf_test_options_t* options) tf_ssb_t* ssb = tf_ssb_create(&loop, NULL, options->db_path, NULL); uint64_t start = uv_hrtime(); - const char** ids = tf_ssb_db_get_all_visible_identities(ssb, 2); - tf_free(ids); + int count = 0; + for (int i = 0; i < 100; i++) + { + const char** ids = tf_ssb_db_get_all_visible_identities(ssb, 2); + while (ids[count]) { count++; } + tf_free(ids); + } uint64_t end = uv_hrtime(); - tf_printf("completed in %.3fs\n", (end - start) / 1e9); + tf_printf("completed in %.3fs (%d ids)\n", (end - start) / 1e9, count); tf_ssb_destroy(ssb);