From f46d8e4f87f06f0a14e0b330cccde804abce93da Mon Sep 17 00:00:00 2001 From: VelikovPetar Date: Wed, 8 Jul 2026 20:28:13 +0200 Subject: [PATCH] perf(persistence): add SQLite indexes to speed up offline channel-list reads (v9) Co-Authored-By: Claude Sonnet 4.6 --- packages/stream_chat_persistence/CHANGELOG.md | 5 +++++ .../lib/src/db/drift_chat_database.dart | 2 +- .../lib/src/db/drift_chat_database.g.dart | 14 +++++++++++++- .../lib/src/entity/members.dart | 1 + .../lib/src/entity/messages.dart | 1 + .../lib/src/entity/reactions.dart | 1 + .../lib/src/entity/reads.dart | 1 + 7 files changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/stream_chat_persistence/CHANGELOG.md b/packages/stream_chat_persistence/CHANGELOG.md index 1c634c73d1..8eff944fb7 100644 --- a/packages/stream_chat_persistence/CHANGELOG.md +++ b/packages/stream_chat_persistence/CHANGELOG.md @@ -4,6 +4,11 @@ - Added support for predefined filters for `QueryChannels` on `StreamChatPersistenceClient`. +🚀 Performance + +- Add indices on the `channel_cid` column on the `Messages`, `Members`, and `Reads` tables to improve read times on large databases. +- Add indices on the `message_id` column on the `Reactions` table to improve read times on large databases. + ## 9.26.0 🐞 Fixed diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart index ed97eb6e73..d489164b03 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.dart @@ -56,7 +56,7 @@ class DriftChatDatabase extends _$DriftChatDatabase { // you should bump this number whenever you change or add a table definition. @override - int get schemaVersion => 30; + int get schemaVersion => 31; // Store DateTime as ISO-8601 text to preserve sub-second precision. @override diff --git a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart index f2f105563d..5186b28210 100644 --- a/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart +++ b/packages/stream_chat_persistence/lib/src/db/drift_chat_database.g.dart @@ -8881,6 +8881,14 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { $ChannelQueriesMetadataTable(this); late final $ConnectionEventsTable connectionEvents = $ConnectionEventsTable(this); + late final Index idxMessagesChannelCid = Index('idx_messages_channel_cid', + 'CREATE INDEX idx_messages_channel_cid ON messages (channel_cid)'); + late final Index idxReactionsMessageId = Index('idx_reactions_message_id', + 'CREATE INDEX idx_reactions_message_id ON reactions (message_id)'); + late final Index idxMembersChannelCid = Index('idx_members_channel_cid', + 'CREATE INDEX idx_members_channel_cid ON members (channel_cid)'); + late final Index idxReadsChannelCid = Index('idx_reads_channel_cid', + 'CREATE INDEX idx_reads_channel_cid ON reads (channel_cid)'); late final UserDao userDao = UserDao(this as DriftChatDatabase); late final ChannelDao channelDao = ChannelDao(this as DriftChatDatabase); late final MessageDao messageDao = MessageDao(this as DriftChatDatabase); @@ -8917,7 +8925,11 @@ abstract class _$DriftChatDatabase extends GeneratedDatabase { reads, channelQueries, channelQueriesMetadata, - connectionEvents + connectionEvents, + idxMessagesChannelCid, + idxReactionsMessageId, + idxMembersChannelCid, + idxReadsChannelCid ]; @override StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules( diff --git a/packages/stream_chat_persistence/lib/src/entity/members.dart b/packages/stream_chat_persistence/lib/src/entity/members.dart index d14948d59b..3d6da2c8d5 100644 --- a/packages/stream_chat_persistence/lib/src/entity/members.dart +++ b/packages/stream_chat_persistence/lib/src/entity/members.dart @@ -5,6 +5,7 @@ import 'package:stream_chat_persistence/src/entity/channels.dart'; /// Represents a [Members] table in [DriftChatDatabase]. @DataClassName('MemberEntity') +@TableIndex(name: 'idx_members_channel_cid', columns: {#channelCid}) class Members extends Table { /// The interested user id TextColumn get userId => text()(); diff --git a/packages/stream_chat_persistence/lib/src/entity/messages.dart b/packages/stream_chat_persistence/lib/src/entity/messages.dart index 3ea3ab19e9..e4607850c6 100644 --- a/packages/stream_chat_persistence/lib/src/entity/messages.dart +++ b/packages/stream_chat_persistence/lib/src/entity/messages.dart @@ -7,6 +7,7 @@ import 'package:stream_chat_persistence/src/entity/channels.dart'; /// Represents a [Messages] table in [DriftChatDatabase]. @DataClassName('MessageEntity') +@TableIndex(name: 'idx_messages_channel_cid', columns: {#channelCid}) class Messages extends Table { /// The message id TextColumn get id => text()(); diff --git a/packages/stream_chat_persistence/lib/src/entity/reactions.dart b/packages/stream_chat_persistence/lib/src/entity/reactions.dart index 7c2a33eec9..80c5d2441c 100644 --- a/packages/stream_chat_persistence/lib/src/entity/reactions.dart +++ b/packages/stream_chat_persistence/lib/src/entity/reactions.dart @@ -5,6 +5,7 @@ import 'package:stream_chat_persistence/src/entity/messages.dart'; /// Represents a [Reactions] table in [DriftChatDatabase]. @DataClassName('ReactionEntity') +@TableIndex(name: 'idx_reactions_message_id', columns: {#messageId}) class Reactions extends Table { /// The id of the user that sent the reaction TextColumn get userId => text()(); diff --git a/packages/stream_chat_persistence/lib/src/entity/reads.dart b/packages/stream_chat_persistence/lib/src/entity/reads.dart index a2bd1f77c1..61e2383cfa 100644 --- a/packages/stream_chat_persistence/lib/src/entity/reads.dart +++ b/packages/stream_chat_persistence/lib/src/entity/reads.dart @@ -4,6 +4,7 @@ import 'package:stream_chat_persistence/src/entity/channels.dart'; /// Represents a [Reads] table in [DriftChatDatabase]. @DataClassName('ReadEntity') +@TableIndex(name: 'idx_reads_channel_cid', columns: {#channelCid}) class Reads extends Table { /// Date of the read event DateTimeColumn get lastRead => dateTime()();