chore: CREATE INDEX CONCURRENTLY for "userId" "id" composite note index

This commit is contained in:
anatawa12 2025-04-30 21:48:40 +09:00
parent 70232d3d73
commit 16236fbc80
No known key found for this signature in database
GPG Key ID: 9CA909848B8E4EA6
3 changed files with 11 additions and 3 deletions

View File

@ -5,9 +5,10 @@
export class CompositeNoteIndex1745378064470 { export class CompositeNoteIndex1745378064470 {
name = 'CompositeNoteIndex1745378064470'; name = 'CompositeNoteIndex1745378064470';
transaction = false;
async up(queryRunner) { 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"`); await queryRunner.query(`DROP INDEX IF EXISTS "IDX_5b87d9d19127bd5d92026017a7"`);
// Flush all cached Linear Scan Plans and redo statistics for composite index // 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 // 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) { async down(queryRunner) {
await queryRunner.query(`DROP INDEX IF EXISTS "IDX_724b311e6f883751f261ebe378"`); 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")`);
} }
} }

View File

@ -14,4 +14,5 @@ export default new DataSource({
extra: config.db.extra, extra: config.db.extra,
entities: entities, entities: entities,
migrations: ['migration/*.js'], migrations: ['migration/*.js'],
migrationsTransactionMode: 'each',
}); });

View File

@ -10,7 +10,13 @@ import { MiUser } from './User.js';
import { MiChannel } from './Channel.js'; import { MiChannel } from './Channel.js';
import type { MiDriveFile } from './DriveFile.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') @Entity('note')
export class MiNote { export class MiNote {
@PrimaryColumn(id()) @PrimaryColumn(id())