mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 12:38:33 +00:00
Add partial index to improve unread count perf.
This commit is contained in:
committed by
Alex Hart
parent
55abd88a03
commit
4600e38a2a
@@ -11,6 +11,7 @@ import org.signal.core.util.Base64
|
|||||||
import org.signal.core.util.Hex
|
import org.signal.core.util.Hex
|
||||||
import org.signal.core.util.concurrent.SignalExecutors
|
import org.signal.core.util.concurrent.SignalExecutors
|
||||||
import org.signal.core.util.isAbsent
|
import org.signal.core.util.isAbsent
|
||||||
|
import org.signal.core.util.roundedString
|
||||||
import org.signal.libsignal.zkgroup.profiles.ProfileKey
|
import org.signal.libsignal.zkgroup.profiles.ProfileKey
|
||||||
import org.thoughtcrime.securesms.MainActivity
|
import org.thoughtcrime.securesms.MainActivity
|
||||||
import org.thoughtcrime.securesms.R
|
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.adapter.mapping.MappingAdapter
|
||||||
import org.thoughtcrime.securesms.util.livedata.Store
|
import org.thoughtcrime.securesms.util.livedata.Store
|
||||||
import java.util.Objects
|
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.
|
* 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) {
|
if (!recipient.isGroup) {
|
||||||
sectionHeaderPref(DSLSettingsText.from("Actions"))
|
sectionHeaderPref(DSLSettingsText.from("Actions"))
|
||||||
|
|
||||||
|
|||||||
@@ -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_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_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_COUNT = "message_thread_count_index"
|
||||||
|
private const val INDEX_THREAD_UNREAD_COUNT = "message_thread_unread_count_index"
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
val CREATE_INDEXS = arrayOf(
|
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 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)",
|
"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
|
// 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(
|
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>? {
|
fun getOldestUnreadMentionDetails(threadId: Long): Pair<RecipientId, Long>? {
|
||||||
return readableDatabase
|
return readableDatabase
|
||||||
.select(FROM_RECIPIENT_ID, DATE_RECEIVED)
|
.select(FROM_RECIPIENT_ID, DATE_RECEIVED)
|
||||||
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
|
.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 $READ = 0 AND $MENTIONS_SELF = 1", threadId)
|
.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")
|
.orderBy("$DATE_RECEIVED ASC")
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.run()
|
.run()
|
||||||
@@ -2290,8 +2293,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||||||
fun getUnreadMentionCount(threadId: Long): Int {
|
fun getUnreadMentionCount(threadId: Long): Int {
|
||||||
return readableDatabase
|
return readableDatabase
|
||||||
.count()
|
.count()
|
||||||
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
|
.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 $READ = 0 AND $MENTIONS_SELF = 1", threadId)
|
.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()
|
.run()
|
||||||
.readToSingleInt()
|
.readToSingleInt()
|
||||||
}
|
}
|
||||||
@@ -4053,8 +4056,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
|||||||
fun getUnreadCount(threadId: Long): Int {
|
fun getUnreadCount(threadId: Long): Int {
|
||||||
return readableDatabase
|
return readableDatabase
|
||||||
.select("COUNT(*)")
|
.select("COUNT(*)")
|
||||||
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
|
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_UNREAD_COUNT")
|
||||||
.where("$READ = 0 AND $STORY_TYPE = 0 AND $THREAD_ID = $threadId AND $PARENT_STORY_ID <= 0 AND $LATEST_REVISION_ID IS NULL")
|
.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()
|
.run()
|
||||||
.readToSingleInt()
|
.readToSingleInt()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.V227_AddAttachmentArchiveTransferState
|
||||||
import org.thoughtcrime.securesms.database.helpers.migration.V228_AddNameCollisionTables
|
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.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.
|
* 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,
|
226 to V226_AddAttachmentMediaIdIndex,
|
||||||
227 to V227_AddAttachmentArchiveTransferState,
|
227 to V227_AddAttachmentArchiveTransferState,
|
||||||
228 to V228_AddNameCollisionTables,
|
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
|
@JvmStatic
|
||||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user