-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
Bug description
Not sure if I'm doing something wrong but create
and createMany
on a table with a CITEXT[] column is much slower than with a TEXT[] column.
On my machine it's about 10 times slower (~30 times slower when the database is running in Docker). I did expect CITEXT to be a bit slower but not by that much. I see the same with CITEXT columns that are not arrays but not quite as severe.
There is barely any performance difference for queries and updates between CITEXT and TEXT.
I tried executing the SQL generated by Prisma in node-postgres directly and didn't see this difference in performance there.
When CITEXT property is undefined
and the column is nullable the difference disappears.
When I set @default([])
on the column in the Prisma schema and do the same I observe decreased performance again.
Which is not that surprising but when I don't set a default in the Prisma schema and then manually set one in the database, the performance improves again.
The SQL generated by Prisma looks fine to me.
BEGIN
DEALLOCATE ALL
INSERT INTO "public"."Foo" ("name","tags") VALUES ($1,$2), ($3,$4), ($5,$6), ($7,$8), ($9,$10), ($11,$12), ($13,$14), ($15,$16), ($17,$18), ($19,$20)
COMMIT
How to reproduce
- have a model with a Citext property and one without
- citext extension installed in the database
- do something like
createMany({ data: [{ citextProperty: [] }, ...] })
and measure the time it takes - do the same for the model where the property is just a regular text
See "Prisma information" for an example
Expected behavior
No response
Prisma information
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Foo {
id Int @id @default(autoincrement())
name String
tags String[] @db.Citext
}
model Bar {
id Int @id @default(autoincrement())
name String
tags String[]
}
import { PrismaClient } from '@prisma/client';
import { performance } from 'perf_hooks';
const prisma = new PrismaClient();
const elementCount = 1000;
async function main() {
const foos: any[] = [];
const bars: any[] = [];
for (let i = 0; i < elementCount; i++) {
foos.push({ name: `foo${i}`, tags: [] });
bars.push({ name: `bar${i}`, tags: [] });
}
const createFoos = () => prisma.foo.createMany({ data: foos });
const createBars = () => prisma.bar.createMany({ data: bars });
await stopwatch(createFoos);
await stopwatch(createBars);
await prisma.foo.deleteMany();
await prisma.bar.deleteMany();
}
async function stopwatch(fn: () => Promise<any>) {
const start = performance.now();
await fn();
const end = performance.now();
console.log(`Time ${fn.name}: ${end - start}ms`);
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});
(order of createFoos
and createBars
can also be reversed to rule out that the additional time is caused by overhead of initializing the connection at the first call)
Environment & setup
- OS: Windows 10
- Database: PostgreSQL 17.3
- Node.js version: v22.12.0
Prisma Version
prisma : 6.3.1
@prisma/client : 6.3.1