diff --git a/packages/backend/migration/1745378064470-composite-note-index.js b/packages/backend/migration/1745378064470-composite-note-index.js index 49e835d38c..773afb636c 100644 --- a/packages/backend/migration/1745378064470-composite-note-index.js +++ b/packages/backend/migration/1745378064470-composite-note-index.js @@ -5,9 +5,10 @@ export class CompositeNoteIndex1745378064470 { name = 'CompositeNoteIndex1745378064470'; + transaction = false; async up(queryRunner) { - await queryRunner.query(`CREATE INDEX "IDX_724b311e6f883751f261ebe378" ON "note" ("userId", "id" DESC)`); + await queryRunner.query(`CREATE INDEX CONCURRENTLY "IDX_724b311e6f883751f261ebe378" ON "note" ("userId", "id" DESC)`); await queryRunner.query(`DROP INDEX IF EXISTS "IDX_5b87d9d19127bd5d92026017a7"`); // Flush all cached Linear Scan Plans and redo statistics for composite index // this is important for Postgres to learn that even in highly complex queries, using this index first can reduce the result set significantly @@ -16,6 +17,6 @@ export class CompositeNoteIndex1745378064470 { async down(queryRunner) { await queryRunner.query(`DROP INDEX IF EXISTS "IDX_724b311e6f883751f261ebe378"`); - await queryRunner.query(`CREATE INDEX "IDX_5b87d9d19127bd5d92026017a7" ON "note" ("userId")`); + await queryRunner.query(`CREATE INDEX CONCURRENTLY "IDX_5b87d9d19127bd5d92026017a7" ON "note" ("userId")`); } } diff --git a/packages/backend/ormconfig.js b/packages/backend/ormconfig.js index 229e5bf1fe..23774f21fd 100644 --- a/packages/backend/ormconfig.js +++ b/packages/backend/ormconfig.js @@ -14,4 +14,5 @@ export default new DataSource({ extra: config.db.extra, entities: entities, migrations: ['migration/*.js'], + migrationsTransactionMode: 'each', }); diff --git a/packages/backend/src/models/Note.ts b/packages/backend/src/models/Note.ts index c5ca2b5776..fe499bdc0b 100644 --- a/packages/backend/src/models/Note.ts +++ b/packages/backend/src/models/Note.ts @@ -10,7 +10,13 @@ import { MiUser } from './User.js'; import { MiChannel } from './Channel.js'; import type { MiDriveFile } from './DriveFile.js'; -@Index(['userId', 'id']) +// Note: When you create a new index for existing column of this table, +// it might be better to index concurrently by setting `{ concurrent: true }`. +// Since this table is very large, and it takes a long time to create index in most cases. +// Please note that `CREATE INDEX CONCURRENTLY` is not supported in transaction, +// so you need to set `transaction = false` in migration. +// Please refer 1745378064470-composite-note-index.js for example. +@Index(['userId', 'id'], { concurrent: true }) @Entity('note') export class MiNote { @PrimaryColumn(id())