Add partial index to improve unread count perf.

This commit is contained in:
Greyson Parrelli 2024-05-02 14:15:50 -04:00 committed by Alex Hart
parent 55abd88a03
commit 4600e38a2a
4 changed files with 47 additions and 9 deletions

View file

@ -11,6 +11,7 @@ import org.signal.core.util.Base64
import org.signal.core.util.Hex
import org.signal.core.util.concurrent.SignalExecutors
import org.signal.core.util.isAbsent
import org.signal.core.util.roundedString
import org.signal.libsignal.zkgroup.profiles.ProfileKey
import org.thoughtcrime.securesms.MainActivity
import org.thoughtcrime.securesms.R
@ -33,6 +34,8 @@ import org.thoughtcrime.securesms.util.Util
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
import org.thoughtcrime.securesms.util.livedata.Store
import java.util.Objects
import kotlin.time.Duration.Companion.nanoseconds
import kotlin.time.DurationUnit
/**
* Shows internal details about a recipient that you can view from the conversation settings.
@ -151,6 +154,17 @@ class InternalConversationSettingsFragment : DSLSettingsFragment(
)
}
clickPref(
title = DSLSettingsText.from("Trigger Thread Update"),
summary = DSLSettingsText.from("Triggers a thread update. Useful for testing perf."),
onClick = {
val startTimeNanos = System.nanoTime()
SignalDatabase.threads.update(state.threadId ?: -1, true)
val endTimeNanos = System.nanoTime()
Toast.makeText(context, "Thread update took ${(endTimeNanos - startTimeNanos).nanoseconds.toDouble(DurationUnit.MILLISECONDS).roundedString(2)} ms", Toast.LENGTH_SHORT).show()
}
)
if (!recipient.isGroup) {
sectionHeaderPref(DSLSettingsText.from("Actions"))

View file

@ -269,6 +269,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
private const val INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID = "message_thread_story_parent_story_scheduled_date_latest_revision_id_index"
private const val INDEX_DATE_SENT_FROM_TO_THREAD = "message_date_sent_from_to_thread_index"
private const val INDEX_THREAD_COUNT = "message_thread_count_index"
private const val INDEX_THREAD_UNREAD_COUNT = "message_thread_unread_count_index"
@JvmField
val CREATE_INDEXS = arrayOf(
@ -289,7 +290,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
"CREATE INDEX IF NOT EXISTS message_to_recipient_id_index ON $TABLE_NAME ($TO_RECIPIENT_ID)",
"CREATE UNIQUE INDEX IF NOT EXISTS message_unique_sent_from_thread ON $TABLE_NAME ($DATE_SENT, $FROM_RECIPIENT_ID, $THREAD_ID)",
// This index is created specifically for getting the number of messages in a thread and therefore needs to be kept in sync with that query
"CREATE INDEX IF NOT EXISTS $INDEX_THREAD_COUNT ON $TABLE_NAME ($THREAD_ID) WHERE $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL"
"CREATE INDEX IF NOT EXISTS $INDEX_THREAD_COUNT ON $TABLE_NAME ($THREAD_ID) WHERE $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL",
// This index is created specifically for getting the number of unread messages in a thread and therefore needs to be kept in sync with that query
"CREATE INDEX IF NOT EXISTS $INDEX_THREAD_UNREAD_COUNT ON $TABLE_NAME ($THREAD_ID) WHERE $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL AND $READ = 0"
)
private val MMS_PROJECTION_BASE = arrayOf(
@ -2274,8 +2277,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun getOldestUnreadMentionDetails(threadId: Long): Pair<RecipientId, Long>? {
return readableDatabase
.select(FROM_RECIPIENT_ID, DATE_RECEIVED)
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
.where("$THREAD_ID = ? AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL AND $READ = 0 AND $MENTIONS_SELF = 1", threadId)
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_UNREAD_COUNT")
.where("$THREAD_ID = ? AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL AND $SCHEDULED_DATE = -1 AND $READ = 0 AND $MENTIONS_SELF = 1", threadId)
.orderBy("$DATE_RECEIVED ASC")
.limit(1)
.run()
@ -2290,8 +2293,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun getUnreadMentionCount(threadId: Long): Int {
return readableDatabase
.count()
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
.where("$THREAD_ID = ? AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL AND $READ = 0 AND $MENTIONS_SELF = 1", threadId)
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_UNREAD_COUNT")
.where("$THREAD_ID = ? AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL AND $SCHEDULED_DATE = -1 AND $READ = 0 AND $MENTIONS_SELF = 1", threadId)
.run()
.readToSingleInt()
}
@ -4053,8 +4056,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun getUnreadCount(threadId: Long): Int {
return readableDatabase
.select("COUNT(*)")
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
.where("$READ = 0 AND $STORY_TYPE = 0 AND $THREAD_ID = $threadId AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL")
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_UNREAD_COUNT")
.where("$THREAD_ID = $threadId AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL AND $SCHEDULED_DATE = -1 AND $READ = 0")
.run()
.readToSingleInt()
}

View file

@ -87,6 +87,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V226_AddAttachmentM
import org.thoughtcrime.securesms.database.helpers.migration.V227_AddAttachmentArchiveTransferState
import org.thoughtcrime.securesms.database.helpers.migration.V228_AddNameCollisionTables
import org.thoughtcrime.securesms.database.helpers.migration.V229_MarkMissedCallEventsNotified
import org.thoughtcrime.securesms.database.helpers.migration.V230_UnreadCountIndices
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@ -176,10 +177,11 @@ object SignalDatabaseMigrations {
226 to V226_AddAttachmentMediaIdIndex,
227 to V227_AddAttachmentArchiveTransferState,
228 to V228_AddNameCollisionTables,
229 to V229_MarkMissedCallEventsNotified
229 to V229_MarkMissedCallEventsNotified,
230 to V230_UnreadCountIndices
)
const val DATABASE_VERSION = 229
const val DATABASE_VERSION = 230
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {

View file

@ -0,0 +1,19 @@
/*
* Copyright 2024 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Adds a partial index for some performance-critical queries around unread counts.
*/
@Suppress("ClassName")
object V230_UnreadCountIndices : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("CREATE INDEX IF NOT EXISTS message_thread_unread_count_index ON message (thread_id) WHERE story_type = 0 AND parent_story_id <= 0 AND scheduled_date = -1 AND latest_revision_id IS NULL AND read = 0")
}
}