porsager / postgres

Postgres.js - The Fastest full featured PostgreSQL client for Node.js, Deno, Bun and CloudFlare
The Unlicense
7.04k stars 257 forks source link

sql.unsafe() with params is 3 times slower than sql.unsafe() without params #794

Closed lnlife closed 3 months ago

lnlife commented 5 months ago

This results 0.3k qps: await sql.unsafe("select * from posts where id=$1",[5])

This results 1.0k qps: await sql.unsafe("select * from posts where id=5")

lnlife commented 5 months ago

Here is the codes:

const sql = postgres(process.env.PG_URL, { max: 1 })
let r = await sql`select * from posts where id=1`

console.time("sql")
for (let i = 1; i <= 500; i++) {
    r = await sql`select * from posts where id=1`
}
console.timeEnd("sql")

console.time("unsafeWithP")
for (let i = 1; i <= 500; i++) {
    r = await sql.unsafe("select * from posts where id=$1", [1])
}
console.timeEnd("unsafeWithP")

console.time("unsafe")
for (let i = 1; i <= 500; i++) {
    r = await sql.unsafe("select * from posts where id=1")
}
console.timeEnd("unsafe")

results:

[40.56ms] sql
[82.65ms] unsafeWithP
[51.31ms] unsafe

unsafe is always 25% slower than sql, and unsafe with params is more slower.

porsager commented 5 months ago

Unsafe without parameters default to a simple query which is why it is faster than unsafe with parameters. Unsafe with parameters are not prepared by default, so to get the speed of reguar sql`` you have to use sql.unsafe(..., [...], { prepare: true })

You can also use { prepare: true } for unsafe without parameters.

lnlife commented 5 months ago

After adding {prepare:true}, sql.unsafe with parameters becomes faster, but sql.unsafe without parameter is still slow, seem {prepared:true} does not affect it.

sql: 48.975ms
unsafeWithP: 52.277ms
unsafe: 64.378ms

Here is the code: r = await sql.unsafe("select * from posts where id=1", [], { prepare: true })

sql.unsafe with out parameter is take higher CPU usage. I have made a benchmark via http multi-concurrency request and it was about 40% slower than sql and sql.unsafe with parameters.

porsager commented 5 months ago

Perhaps the implicit simple logic takes over. Worth looking into. With prepare: true it should not fall back to a simple query, so this looks like a bug.

porsager commented 3 months ago

Queries seem to be executed as expected, and I'm not seeing anything out of the ordinary if I do a proper benchmark with variations and warmup.