Improve speed of getUnreadByConversationAndMarkRead query

This commit is contained in:
trevor-signal
2025-11-13 14:00:35 -05:00
committed by GitHub
parent 8e79bb5050
commit 616fd1a536
5 changed files with 36 additions and 19 deletions

View File

@@ -3351,6 +3351,7 @@ function getUnreadByConversationAndMarkRead(
const updateExpirationFragment = sqlFragment` const updateExpirationFragment = sqlFragment`
UPDATE messages UPDATE messages
INDEXED BY messages_conversationId_expirationStartTimestamp
SET SET
expirationStartTimestamp = ${expirationStartTimestamp} expirationStartTimestamp = ${expirationStartTimestamp}
WHERE WHERE

View File

@@ -3,18 +3,15 @@
import type { Database } from '@signalapp/sqlcipher'; import type { Database } from '@signalapp/sqlcipher';
export default function updateToSchemaVersion1520(db: Database): void { export default function updateToSchemaVersion1530(db: Database): void {
db.exec(
'DROP INDEX IF EXISTS expiring_message_by_conversation_and_received_at;'
);
db.exec(` db.exec(`
ALTER TABLE messages ADD COLUMN hasExpireTimer INTEGER NOT NULL ALTER TABLE messages ADD COLUMN hasExpireTimer INTEGER NOT NULL
GENERATED ALWAYS AS (COALESCE(expireTimer, 0) > 0) VIRTUAL; GENERATED ALWAYS AS (COALESCE(expireTimer, 0) > 0) VIRTUAL;
`); `);
db.exec(` // Deprecated by migration 1540
CREATE INDEX messages_conversationId_hasExpireTimer_expirationStartTimestamp // db.exec(`
ON messages (conversationId, hasExpireTimer, expirationStartTimestamp); // CREATE INDEX messages_conversationId_hasExpireTimer_expirationStartTimestamp
`); // ON messages (conversationId, hasExpireTimer, expirationStartTimestamp);
// `);
} }

View File

@@ -0,0 +1,16 @@
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Database } from '@signalapp/sqlcipher';
export default function updateToSchemaVersion1540(db: Database): void {
db.exec(
'DROP INDEX IF EXISTS messages_conversationId_hasExpireTimer_expirationStartTimestamp;'
);
db.exec(`
CREATE INDEX messages_conversationId_expirationStartTimestamp
ON messages (conversationId, expirationStartTimestamp)
WHERE hasExpireTimer IS 1;
`);
}

View File

@@ -129,6 +129,7 @@ import updateToSchemaVersion1500 from './1500-search-polls.std.js';
import updateToSchemaVersion1510 from './1510-chat-folders-normalize-all-chats.std.js'; import updateToSchemaVersion1510 from './1510-chat-folders-normalize-all-chats.std.js';
import updateToSchemaVersion1520 from './1520-poll-votes-unread.std.js'; import updateToSchemaVersion1520 from './1520-poll-votes-unread.std.js';
import updateToSchemaVersion1530 from './1530-update-expiring-index.std.js'; import updateToSchemaVersion1530 from './1530-update-expiring-index.std.js';
import updateToSchemaVersion1540 from './1540-partial-expiring-index.std.js';
import { DataWriter } from '../Server.node.js'; import { DataWriter } from '../Server.node.js';
@@ -1616,6 +1617,7 @@ export const SCHEMA_VERSIONS: ReadonlyArray<SchemaUpdateType> = [
{ version: 1510, update: updateToSchemaVersion1510 }, { version: 1510, update: updateToSchemaVersion1510 },
{ version: 1520, update: updateToSchemaVersion1520 }, { version: 1520, update: updateToSchemaVersion1520 },
{ version: 1530, update: updateToSchemaVersion1530 }, { version: 1530, update: updateToSchemaVersion1530 },
{ version: 1540, update: updateToSchemaVersion1540 },
]; ];
export class DBVersionFromFutureError extends Error { export class DBVersionFromFutureError extends Error {

View File

@@ -6,12 +6,12 @@ import { type WritableDB } from '../../sql/Interface.std.js';
import { sql, sqlFragment } from '../../sql/util.std.js'; import { sql, sqlFragment } from '../../sql/util.std.js';
import { createDB, explain, updateToVersion } from './helpers.node.js'; import { createDB, explain, updateToVersion } from './helpers.node.js';
describe('SQL/updateToSchemaVersion1530', () => { describe('SQL/updateToSchemaVersion1540', () => {
let db: WritableDB; let db: WritableDB;
beforeEach(() => { beforeEach(() => {
db = createDB(); db = createDB();
updateToVersion(db, 1530); updateToVersion(db, 1540);
}); });
afterEach(() => { afterEach(() => {
db.close(); db.close();
@@ -19,6 +19,7 @@ describe('SQL/updateToSchemaVersion1530', () => {
const CORE_UPDATE_QUERY = sqlFragment` const CORE_UPDATE_QUERY = sqlFragment`
UPDATE messages UPDATE messages
INDEXED BY messages_conversationId_expirationStartTimestamp
SET SET
expirationStartTimestamp = 342342 expirationStartTimestamp = 342342
WHERE WHERE
@@ -48,8 +49,8 @@ describe('SQL/updateToSchemaVersion1530', () => {
assert.strictEqual( assert.strictEqual(
detail, detail,
'SEARCH messages USING INDEX messages_conversationId_hasExpireTimer_expirationStartTimestamp' + 'SEARCH messages USING INDEX messages_conversationId_expirationStartTimestamp' +
' (conversationId=? AND hasExpireTimer=? AND expirationStartTimestamp=?)' ' (conversationId=? AND expirationStartTimestamp=?)'
); );
}); });
it('uses index efficiently with null start + no storyId condition', () => { it('uses index efficiently with null start + no storyId condition', () => {
@@ -62,8 +63,8 @@ describe('SQL/updateToSchemaVersion1530', () => {
assert.strictEqual( assert.strictEqual(
detail, detail,
'SEARCH messages USING INDEX messages_conversationId_hasExpireTimer_expirationStartTimestamp' + 'SEARCH messages USING INDEX messages_conversationId_expirationStartTimestamp' +
' (conversationId=? AND hasExpireTimer=? AND expirationStartTimestamp=?)' ' (conversationId=? AND expirationStartTimestamp=?)'
); );
}); });
@@ -72,8 +73,8 @@ describe('SQL/updateToSchemaVersion1530', () => {
assert.strictEqual( assert.strictEqual(
detail, detail,
'SEARCH messages USING INDEX messages_conversationId_hasExpireTimer_expirationStartTimestamp' + 'SEARCH messages USING INDEX messages_conversationId_expirationStartTimestamp' +
' (conversationId=? AND hasExpireTimer=? AND expirationStartTimestamp>?)' ' (conversationId=? AND expirationStartTimestamp>?)'
); );
}); });
@@ -86,8 +87,8 @@ describe('SQL/updateToSchemaVersion1530', () => {
assert.strictEqual( assert.strictEqual(
detail, detail,
'SEARCH messages USING INDEX messages_conversationId_hasExpireTimer_expirationStartTimestamp' + 'SEARCH messages USING INDEX messages_conversationId_expirationStartTimestamp' +
' (conversationId=? AND hasExpireTimer=? AND expirationStartTimestamp>?)' ' (conversationId=? AND expirationStartTimestamp>?)'
); );
}); });
}); });