From bf73954f429b668d78ff3e9d88af20fc581a4353 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Fri, 29 May 2026 15:42:23 -0400 Subject: [PATCH] Add indexes for slow database queries and optimize view-once query. --- .../securesms/database/AttachmentTable.kt | 3 +- .../securesms/database/MessageTable.kt | 40 ++++++++----------- .../helpers/SignalDatabaseMigrations.kt | 6 ++- .../V319_AddAttachmentAndMessageIndexes.kt | 13 ++++++ 4 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V319_AddAttachmentAndMessageIndexes.kt diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt index c56ca293b1..ef9bb1f715 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentTable.kt @@ -298,7 +298,8 @@ class AttachmentTable( "CREATE INDEX IF NOT EXISTS attachment_archive_transfer_state ON $TABLE_NAME ($ARCHIVE_TRANSFER_STATE);", "CREATE INDEX IF NOT EXISTS attachment_remote_digest_index ON $TABLE_NAME ($REMOTE_DIGEST);", "CREATE INDEX IF NOT EXISTS attachment_metadata_id ON $TABLE_NAME ($METADATA_ID);", - "CREATE INDEX IF NOT EXISTS attachment_media_overview_size ON $TABLE_NAME ($DATA_SIZE DESC, $DISPLAY_ORDER DESC) WHERE $QUOTE = 0 AND $STICKER_PACK_ID IS NULL AND $DATA_FILE IS NOT NULL" + "CREATE INDEX IF NOT EXISTS attachment_media_overview_size ON $TABLE_NAME ($DATA_SIZE DESC, $DISPLAY_ORDER DESC) WHERE $QUOTE = 0 AND $STICKER_PACK_ID IS NULL AND $DATA_FILE IS NOT NULL", + "CREATE INDEX IF NOT EXISTS attachment_archive_thumbnail_transfer_state ON $TABLE_NAME ($ARCHIVE_THUMBNAIL_TRANSFER_STATE)" ) private val DATA_FILE_INFO_PROJECTION = arrayOf( diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index e3ff070108..dbe72c0922 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -138,7 +138,6 @@ import org.thoughtcrime.securesms.polls.PollRecord import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo -import org.thoughtcrime.securesms.revealable.ViewOnceUtil import org.thoughtcrime.securesms.sms.GroupV2UpdateMessageUtil import org.thoughtcrime.securesms.stories.Stories.isFeatureEnabled import org.thoughtcrime.securesms.util.DateUtils @@ -352,7 +351,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat "CREATE INDEX IF NOT EXISTS $INDEX_STARRED ON $TABLE_NAME ($STARRED) WHERE $STARRED > 0", "CREATE INDEX IF NOT EXISTS message_collapsed_state_index ON $TABLE_NAME ($COLLAPSED_STATE)", "CREATE INDEX IF NOT EXISTS message_collapsed_head_id_index ON $TABLE_NAME ($COLLAPSED_HEAD_ID)", - "CREATE INDEX IF NOT EXISTS $INDEX_NOTIFICATION_STATE ON $TABLE_NAME ($DATE_RECEIVED) WHERE $NOTIFIED = 0 AND $STORY_TYPE = 0 AND $LATEST_REVISION_ID IS NULL" + "CREATE INDEX IF NOT EXISTS $INDEX_NOTIFICATION_STATE ON $TABLE_NAME ($DATE_RECEIVED) WHERE $NOTIFIED = 0 AND $STORY_TYPE = 0 AND $LATEST_REVISION_ID IS NULL", + "CREATE INDEX IF NOT EXISTS message_expire_started_index ON $TABLE_NAME ($EXPIRE_STARTED) WHERE $EXPIRE_STARTED > 0", + "CREATE INDEX IF NOT EXISTS message_view_once_index ON $TABLE_NAME ($VIEW_ONCE) WHERE $VIEW_ONCE > 0" ) private val MMS_PROJECTION_BASE = arrayOf( @@ -4461,34 +4462,25 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat fun getNearestExpiringViewOnceMessage(): ViewOnceExpirationInfo? { val query = """ - SELECT - $TABLE_NAME.$ID, - $VIEW_ONCE, - $DATE_RECEIVED - FROM - $TABLE_NAME INNER JOIN ${AttachmentTable.TABLE_NAME} ON $TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID} - WHERE - $VIEW_ONCE > 0 AND + SELECT + $TABLE_NAME.$ID, + $VIEW_ONCE, + $DATE_RECEIVED + FROM + $TABLE_NAME INNER JOIN ${AttachmentTable.TABLE_NAME} ON $TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID} + WHERE + $VIEW_ONCE > 0 AND (${AttachmentTable.DATA_FILE} NOT NULL OR ${AttachmentTable.TRANSFER_STATE} != ?) + ORDER BY $DATE_RECEIVED ASC + LIMIT 1 """ val args = buildArgs(AttachmentTable.TRANSFER_PROGRESS_DONE) - var info: ViewOnceExpirationInfo? = null - var nearestExpiration = Long.MAX_VALUE - - readableDatabase.rawQuery(query, args).forEach { cursor -> - val id = cursor.requireLong(ID) - val dateReceived = cursor.requireLong(DATE_RECEIVED) - val expiresAt = dateReceived + ViewOnceUtil.MAX_LIFESPAN - - if (info == null || expiresAt < nearestExpiration) { - info = ViewOnceExpirationInfo(id, dateReceived) - nearestExpiration = expiresAt + return readableDatabase.rawQuery(query, args) + .readToSingleObject { cursor -> + ViewOnceExpirationInfo(cursor.requireLong(ID), cursor.requireLong(DATE_RECEIVED)) } - } - - return info } /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt index acaee706c0..931caecd37 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt @@ -171,6 +171,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V315_CleanupE164Sen import org.thoughtcrime.securesms.database.helpers.migration.V316_AddVerifiedGroupNameHashMigration import org.thoughtcrime.securesms.database.helpers.migration.V317_AddMessageThreadDateReceivedUnreadIndex import org.thoughtcrime.securesms.database.helpers.migration.V318_AddMessageNotificationStateIndex +import org.thoughtcrime.securesms.database.helpers.migration.V319_AddAttachmentAndMessageIndexes import org.thoughtcrime.securesms.database.SQLiteDatabase as SignalSqliteDatabase /** @@ -349,10 +350,11 @@ object SignalDatabaseMigrations { 315 to V315_CleanupE164SenderKeyShared, 316 to V316_AddVerifiedGroupNameHashMigration, 317 to V317_AddMessageThreadDateReceivedUnreadIndex, - 318 to V318_AddMessageNotificationStateIndex + 318 to V318_AddMessageNotificationStateIndex, + 319 to V319_AddAttachmentAndMessageIndexes ) - const val DATABASE_VERSION = 318 + const val DATABASE_VERSION = 319 @JvmStatic fun migrate(context: Application, db: SignalSqliteDatabase, oldVersion: Int, newVersion: Int) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V319_AddAttachmentAndMessageIndexes.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V319_AddAttachmentAndMessageIndexes.kt new file mode 100644 index 0000000000..9591863b49 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V319_AddAttachmentAndMessageIndexes.kt @@ -0,0 +1,13 @@ +package org.thoughtcrime.securesms.database.helpers.migration + +import android.app.Application +import org.thoughtcrime.securesms.database.SQLiteDatabase + +@Suppress("ClassName") +object V319_AddAttachmentAndMessageIndexes : SignalDatabaseMigration { + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL("CREATE INDEX IF NOT EXISTS message_expire_started_index ON message (expire_started) WHERE expire_started > 0") + db.execSQL("CREATE INDEX IF NOT EXISTS message_view_once_index ON message (view_once) WHERE view_once > 0") + db.execSQL("CREATE INDEX IF NOT EXISTS attachment_archive_thumbnail_transfer_state ON attachment (archive_thumbnail_transfer_state)") + } +}