Improve the performance of detecting duplicate messages.

To do this, we do two things:
- Make the index on DATE_SENT also include the other relevant fields:
the recipientId and threadId
- Use the most minimal projection possible
This commit is contained in:
Greyson Parrelli 2021-06-21 09:51:51 -04:00 committed by GitHub
parent 0d254e0724
commit 5f1454aeb8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 19 deletions

View file

@ -192,7 +192,7 @@ public class MmsDatabase extends MessageDatabase {
"CREATE INDEX IF NOT EXISTS mms_read_index ON " + TABLE_NAME + " (" + READ + ");",
"CREATE INDEX IF NOT EXISTS mms_read_and_notified_and_thread_id_index ON " + TABLE_NAME + "(" + READ + "," + NOTIFIED + "," + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS mms_message_box_index ON " + TABLE_NAME + " (" + MESSAGE_BOX + ");",
"CREATE INDEX IF NOT EXISTS mms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ");",
"CREATE INDEX IF NOT EXISTS mms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ", " + RECIPIENT_ID + ", " + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS mms_date_server_index ON " + TABLE_NAME + " (" + DATE_SERVER + ");",
"CREATE INDEX IF NOT EXISTS mms_thread_date_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");",
"CREATE INDEX IF NOT EXISTS mms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");"
@ -1725,15 +1725,12 @@ public class MmsDatabase extends MessageDatabase {
}
private boolean isDuplicate(IncomingMediaMessage message, long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + RECIPIENT_ID + " = ? AND " + THREAD_ID + " = ?",
new String[]{String.valueOf(message.getSentTimeMillis()), message.getFrom().serialize(), String.valueOf(threadId)},
null, null, null, "1");
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = DATE_SENT + " = ? AND " + RECIPIENT_ID + " = ? AND " + THREAD_ID + " = ?";
String[] args = SqlUtil.buildArgs(message.getSentTimeMillis(), message.getFrom().serialize(), threadId);
try {
return cursor != null && cursor.moveToFirst();
} finally {
if (cursor != null) cursor.close();
try (Cursor cursor = db.query(TABLE_NAME, new String[] { "1" }, query, args, null, null, null, "1")) {
return cursor.moveToFirst();
}
}

View file

@ -131,7 +131,7 @@ public class SmsDatabase extends MessageDatabase {
"CREATE INDEX IF NOT EXISTS sms_read_index ON " + TABLE_NAME + " (" + READ + ");",
"CREATE INDEX IF NOT EXISTS sms_read_and_notified_and_thread_id_index ON " + TABLE_NAME + "(" + READ + "," + NOTIFIED + "," + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS sms_type_index ON " + TABLE_NAME + " (" + TYPE + ");",
"CREATE INDEX IF NOT EXISTS sms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ");",
"CREATE INDEX IF NOT EXISTS sms_date_sent_index ON " + TABLE_NAME + " (" + DATE_SENT + ", " + RECIPIENT_ID + ", " + THREAD_ID + ");",
"CREATE INDEX IF NOT EXISTS sms_date_server_index ON " + TABLE_NAME + " (" + DATE_SERVER + ");",
"CREATE INDEX IF NOT EXISTS sms_thread_date_index ON " + TABLE_NAME + " (" + THREAD_ID + ", " + DATE_RECEIVED + ");",
"CREATE INDEX IF NOT EXISTS sms_reactions_unread_index ON " + TABLE_NAME + " (" + REACTIONS_UNREAD + ");"
@ -1321,15 +1321,12 @@ public class SmsDatabase extends MessageDatabase {
}
private boolean isDuplicate(IncomingTextMessage message, long threadId) {
SQLiteDatabase database = databaseHelper.getReadableDatabase();
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + RECIPIENT_ID + " = ? AND " + THREAD_ID + " = ?",
new String[]{String.valueOf(message.getSentTimestampMillis()), message.getSender().serialize(), String.valueOf(threadId)},
null, null, null, "1");
SQLiteDatabase db = databaseHelper.getReadableDatabase();
String query = DATE_SENT + " = ? AND " + RECIPIENT_ID + " = ? AND " + THREAD_ID + " = ?";
String[] args = SqlUtil.buildArgs(message.getSentTimestampMillis(), message.getSender().serialize(), threadId);
try {
return cursor != null && cursor.moveToFirst();
} finally {
if (cursor != null) cursor.close();
try (Cursor cursor = db.query(TABLE_NAME, new String[] { "1" }, query, args, null, null, null, "1")) {
return cursor.moveToFirst();
}
}

View file

@ -198,8 +198,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
private static final int AVATAR_COLORS = 101;
private static final int EMOJI_SEARCH = 102;
private static final int SENDER_KEY = 103;
private static final int MESSAGE_DUPE_INDEX = 104;
private static final int DATABASE_VERSION = 103;
private static final int DATABASE_VERSION = 104;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@ -1560,6 +1561,14 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab
}
}
if (oldVersion < MESSAGE_DUPE_INDEX) {
db.execSQL("DROP INDEX sms_date_sent_index");
db.execSQL("CREATE INDEX sms_date_sent_index on sms(date_sent, address, thread_id)");
db.execSQL("DROP INDEX mms_date_sent_index");
db.execSQL("CREATE INDEX mms_date_sent_index on mms(date, address, thread_id)");
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();