Using Migrate commands is far slower than running the generated SQL directly
See original GitHub issueThis comes from user feedback (see public Slack https://prisma.slack.com/archives/C01739JGFCM/p1623316160017500) that I am reproducing and summarizing here:
As a side note, we noticed that Prisma migrations are slow, in the order of 5-7 seconds for an empty db with 5 tables and 10 migrations (so the strategy of dropping and recreating a db for absolute certainty of no state spillover is not viable)
those were our timings: re: using
prisma migrate
vs manual SQL queries for migrations, over 3 tries: (note that for the prisma migrate commands, I’m usingexec
that spawns a child process, as prisma doesn’t allow for programmatic migration-running directly)
prisma migrate dev --name init
(recommended in their docs): 5.67s-7.71sprisma migrate deploy
(likely faster since it doesn’t need to read the schema file; yesterday up to 6s as well): 1.64s-2.85s- [plain direct postgres client] implementation: 0.11s-0.30s
This is the plain implementation:
// Drop all tables
await this.pgClient.query('DROP SCHEMA IF EXISTS public CASCADE;');
await this.pgClient.query('CREATE SCHEMA public;');
// Manually fetch and execute migrations as this is faster than `prisma migrate`
const migrations = await getMigrations();
for (const migrationSql of migrations) {
// eslint-disable-next-line no-await-in-loop
await this.pgClient.query(migrationSql.toString());
}
...
import path from 'path';
import { readdir, readFile } from 'fs/promises';
async function getMigrations(): Promise<string[]> {
const migrationsDirPath = path.resolve(__dirname, '../prisma/migrations');
const filePaths = (await readdir(migrationsDirPath))
.sort()
.filter((migrationName) => !migrationName.includes('migration_lock.toml'))
.map((migrationName) => path.resolve(migrationsDirPath, migrationName, 'migration.sql'));
const files = await Promise.all(filePaths.map((filePath) => readFile(filePath)));
return files.map((file) => file.toString());
}
So reproduction here would be to create a project with a schema with 5 models, and 10 migrations to get there. Then use prisma migrate dev
and prisma migrate deploy
to set this project up in an empty database - manually or via exec
in a script, then compare to using the script from the snippet above. (Possibly also compare to prisma db push
to complete the picture.)
If the times really are off as the quote above implies, we might have something to improve on our side. If not, we need to ask for more information and try to get to a reproduction.
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (5 by maintainers)
Top GitHub Comments
It is indeed slower. I will mark this as an improvement rather than a bug.
There is also overhead of sending jsonrpc to the migration engine. I guess starting the up the engine itself will also account for some time.
Note: on the happy path, we do two roundtrips to the migrations table for each migration, one to write that we are going to apply the migration, and the second one to write that the migration finished applying. In activerecord for example, there is only the second one. The price of that is that when a migration failed, you cannot tell 1. that a migration failed, 2. which one, from looking only at the migrations table.