Optimize some indices and queries

This commit is contained in:
Fedor Indutny 2023-01-17 13:07:21 -08:00 committed by GitHub
parent 4a3ffe07e8
commit 1c22fe653c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 71 additions and 33 deletions

View file

@ -1068,7 +1068,7 @@ async function deleteSentProtoRecipient(
const remainingDevices = prepare( const remainingDevices = prepare(
db, db,
` `
SELECT count(*) FROM sendLogRecipients SELECT count(1) FROM sendLogRecipients
WHERE payloadId = $id AND recipientUuid = $recipientUuid; WHERE payloadId = $id AND recipientUuid = $recipientUuid;
` `
) )
@ -1094,7 +1094,7 @@ async function deleteSentProtoRecipient(
// 5. See how many more recipients there were for this payload. // 5. See how many more recipients there were for this payload.
const remainingTotal = prepare( const remainingTotal = prepare(
db, db,
'SELECT count(*) FROM sendLogRecipients WHERE payloadId = $id;' 'SELECT count(1) FROM sendLogRecipients WHERE payloadId = $id;'
) )
.pluck(true) .pluck(true)
.get({ id }); .get({ id });
@ -1748,7 +1748,7 @@ function getMessageCountSync(
const count = db const count = db
.prepare<Query>( .prepare<Query>(
` `
SELECT count(*) SELECT count(1)
FROM messages FROM messages
WHERE conversationId = $conversationId; WHERE conversationId = $conversationId;
` `
@ -1764,7 +1764,7 @@ async function getStoryCount(conversationId: string): Promise<number> {
return db return db
.prepare<Query>( .prepare<Query>(
` `
SELECT count(*) SELECT count(1)
FROM messages FROM messages
WHERE conversationId = $conversationId AND isStory = 1; WHERE conversationId = $conversationId AND isStory = 1;
` `
@ -1787,9 +1787,10 @@ function hasUserInitiatedMessages(conversationId: string): boolean {
` `
SELECT EXISTS( SELECT EXISTS(
SELECT 1 FROM messages SELECT 1 FROM messages
INDEXED BY message_user_initiated
WHERE WHERE
conversationId = $conversationId AND conversationId IS $conversationId AND
isUserInitiatedMessage = 1 isUserInitiatedMessage IS 1
); );
` `
) )
@ -2310,10 +2311,11 @@ async function getUnreadReactionsAndMarkRead({
` `
SELECT reactions.rowid, targetAuthorUuid, targetTimestamp, messageId SELECT reactions.rowid, targetAuthorUuid, targetTimestamp, messageId
FROM reactions FROM reactions
INDEXED BY reactions_unread
JOIN messages on messages.id IS reactions.messageId JOIN messages on messages.id IS reactions.messageId
WHERE WHERE
unread > 0 AND reactions.conversationId IS $conversationId AND
messages.conversationId IS $conversationId AND reactions.unread > 0 AND
messages.received_at <= $newestUnreadAt AND messages.received_at <= $newestUnreadAt AND
messages.storyId IS $storyId messages.storyId IS $storyId
ORDER BY messageReceivedAt DESC; ORDER BY messageReceivedAt DESC;
@ -2329,8 +2331,9 @@ async function getUnreadReactionsAndMarkRead({
batchMultiVarQuery(db, idsToUpdate, (ids: ReadonlyArray<number>): void => { batchMultiVarQuery(db, idsToUpdate, (ids: ReadonlyArray<number>): void => {
db.prepare<ArrayQuery>( db.prepare<ArrayQuery>(
` `
UPDATE reactions SET UPDATE reactions
unread = 0 WHERE rowid IN ( ${ids.map(() => '?').join(', ')} ); SET unread = 0
WHERE rowid IN ( ${ids.map(() => '?').join(', ')} );
` `
).run(ids); ).run(ids);
}); });
@ -2704,8 +2707,9 @@ function getLastConversationActivity({
db, db,
` `
SELECT json FROM messages SELECT json FROM messages
INDEXED BY messages_activity
WHERE WHERE
conversationId = $conversationId AND conversationId IS $conversationId AND
shouldAffectActivity IS 1 AND shouldAffectActivity IS 1 AND
isTimerChangeFromSync IS 0 AND isTimerChangeFromSync IS 0 AND
${includeStoryReplies ? '' : 'storyId IS NULL AND'} ${includeStoryReplies ? '' : 'storyId IS NULL AND'}
@ -2736,8 +2740,9 @@ function getLastConversationPreview({
db, db,
` `
SELECT json FROM messages SELECT json FROM messages
INDEXED BY messages_preview
WHERE WHERE
conversationId = $conversationId AND conversationId IS $conversationId AND
shouldAffectPreview IS 1 AND shouldAffectPreview IS 1 AND
isGroupLeaveEventFromOther IS 0 AND isGroupLeaveEventFromOther IS 0 AND
${includeStoryReplies ? '' : 'storyId IS NULL AND'} ${includeStoryReplies ? '' : 'storyId IS NULL AND'}
@ -2872,7 +2877,7 @@ function getTotalUnreadForConversationSync(
const row = db const row = db
.prepare<Query>( .prepare<Query>(
` `
SELECT count(id) SELECT count(1)
FROM messages FROM messages
WHERE WHERE
conversationId = $conversationId AND conversationId = $conversationId AND
@ -2881,16 +2886,13 @@ function getTotalUnreadForConversationSync(
(${_storyIdPredicate(storyId, includeStoryReplies)}) (${_storyIdPredicate(storyId, includeStoryReplies)})
` `
) )
.pluck()
.get({ .get({
conversationId, conversationId,
storyId: storyId || null, storyId: storyId || null,
}); });
if (!row) { return row;
throw new Error('getTotalUnreadForConversation: Unable to get count');
}
return row['count(id)'];
} }
function getTotalUnseenForConversationSync( function getTotalUnseenForConversationSync(
conversationId: string, conversationId: string,
@ -2906,7 +2908,7 @@ function getTotalUnseenForConversationSync(
const row = db const row = db
.prepare<Query>( .prepare<Query>(
` `
SELECT count(id) SELECT count(1)
FROM messages FROM messages
WHERE WHERE
conversationId = $conversationId AND conversationId = $conversationId AND
@ -2915,16 +2917,13 @@ function getTotalUnseenForConversationSync(
(${_storyIdPredicate(storyId, includeStoryReplies)}) (${_storyIdPredicate(storyId, includeStoryReplies)})
` `
) )
.pluck()
.get({ .get({
conversationId, conversationId,
storyId: storyId || null, storyId: storyId || null,
}); });
if (!row) { return row;
throw new Error('getTotalUnseenForConversationSync: Unable to get count');
}
return row['count(id)'];
} }
async function getMessageMetricsForConversation( async function getMessageMetricsForConversation(
@ -3971,20 +3970,15 @@ async function deleteStickerPackReference(
packId, packId,
}); });
const countRow = db const count = db
.prepare<Query>( .prepare<Query>(
` `
SELECT count(*) FROM sticker_references SELECT count(1) FROM sticker_references
WHERE packId = $packId; WHERE packId = $packId;
` `
) )
.pluck()
.get({ packId }); .get({ packId });
if (!countRow) {
throw new Error(
'deleteStickerPackReference: Unable to get count of references'
);
}
const count = countRow['count(*)'];
if (count > 0) { if (count > 0) {
return undefined; return undefined;
} }
@ -4827,7 +4821,7 @@ async function countStoryReadsByConversation(
return db return db
.prepare<Query>( .prepare<Query>(
` `
SELECT COUNT(storyId) FROM storyReads SELECT count(1) FROM storyReads
WHERE conversationId = $conversationId; WHERE conversationId = $conversationId;
` `
) )

View file

@ -0,0 +1,39 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import type { Database } from '@signalapp/better-sqlite3';
import type { LoggerType } from '../../types/Logging';
export default function updateToSchemaVersion74(
currentVersion: number,
db: Database,
logger: LoggerType
): void {
if (currentVersion >= 74) {
return;
}
db.transaction(() => {
db.exec(
`
-- Previously: (isUserInitiatedMessage)
DROP INDEX message_user_initiated;
CREATE INDEX message_user_initiated ON messages (conversationId, isUserInitiatedMessage);
-- Previously: (unread, conversationId)
DROP INDEX reactions_unread;
CREATE INDEX reactions_unread ON reactions (
conversationId,
unread
);
`
);
db.pragma('user_version = 74');
})();
logger.info('updateToSchemaVersion74: success!');
}

View file

@ -49,6 +49,7 @@ import updateToSchemaVersion70 from './70-story-reply-index';
import updateToSchemaVersion71 from './71-merge-notifications'; import updateToSchemaVersion71 from './71-merge-notifications';
import updateToSchemaVersion72 from './72-optimize-call-id-message-lookup'; import updateToSchemaVersion72 from './72-optimize-call-id-message-lookup';
import updateToSchemaVersion73 from './73-remove-phone-number-discovery'; import updateToSchemaVersion73 from './73-remove-phone-number-discovery';
import updateToSchemaVersion74 from './74-optimize-convo-open';
function updateToSchemaVersion1( function updateToSchemaVersion1(
currentVersion: number, currentVersion: number,
@ -1967,6 +1968,7 @@ export const SCHEMA_VERSIONS = [
updateToSchemaVersion71, updateToSchemaVersion71,
updateToSchemaVersion72, updateToSchemaVersion72,
updateToSchemaVersion73, updateToSchemaVersion73,
updateToSchemaVersion74,
]; ];
export function updateSchema(db: Database, logger: LoggerType): void { export function updateSchema(db: Database, logger: LoggerType): void {
@ -1999,6 +2001,9 @@ export function updateSchema(db: Database, logger: LoggerType): void {
} }
if (userVersion !== maxUserVersion) { if (userVersion !== maxUserVersion) {
const start = Date.now();
db.pragma('optimize'); db.pragma('optimize');
const duration = Date.now() - start;
logger.info(`updateSchema: optimize took ${duration}ms`);
} }
} }