我尝试过这两种方法(游标和偏移量)通过我的~1000 doc分页,但是,我不能让游标比偏移量更快。
// cursor method
const allDocs = []
let queryResults = await prismaClient.obsidian.findMany({
take: 100
})
while (queryResults.length > 0) {
allDocs.push(...queryResults)
queryResults = await prismaClient.obsidian.findMany({
take: 100,
skip: 1,
cursor: {
id: queryResults[queryResults.length - 1]!.id
}
})
}
return allDocs用~25秒完成(注:它似乎在使用OFFSET,我以为它不应该这么做?)
Query: SELECT "public"."obsidian"."id", "public"."obsidian"."doc", "public"."obsidian"."createdAt", "public"."obsidian"."updatedAt", "public"."obsidian"."filename" FROM "public"."obsidian", (SELECT "public"."obsidian"."id" AS "obsidian_id_0" FROM "public"."obsidian" WHERE ("public"."obsidian"."id") = ($1)) AS "order_cmp" WHERE "public"."obsidian"."id" >= "order_cmp"."obsidian_id_0" ORDER BY "public"."obsidian"."id" ASC LIMIT $2 **OFFSET** $3 // offset method
const count = await prismaClient.obsidian.count()
const pages = Math.ceil(count / 100)
const allDocsPromises = []
for (let i = 0; i < pages; i++) {
const page = prismaClient.obsidian.findMany({
skip: i * 100,
take: 100
})
allDocsPromises.push(page)
}
const allDocs = await Promise.all(allDocsPromises)
return _.flatten(allDocs)用~14秒完成。我的想法是,offset方法由于Promise.all()而运行得更快,但是是否有一种方法可以使光标分页以超快的速度返回所有文档?
发布于 2022-08-07 19:21:28
Prisma正在使用一些内部机制来缓冲数据,以加速和解决N+1问题。但在某些情况下,这会导致业绩不佳。
这是一个prisma中间件,可以绕过它的机制并加快速度。如果你认为你跑得慢,你可以试一试。
prisma.$use(async (params, next) => {
if (params.args?.cursor) {
const key = _.lowerFirst(params.model)
const result = await prisma[key].findUniqueOrThrow({
where: params.args.cursor,
select: params.args.orderBy ? _(params.args.orderBy).mapValues(x => true).value() : undefined,
})
params.args.where = {
...params.args.where,
..._(params.args.cursor).mapValues((x, k) => ({
[x === 'desc' ? 'lte' : 'gte']: result[k],
})).value(),
..._(params.args.orderBy).mapValues((x, k) => ({
[x === 'desc' ? 'lte' : 'gte']: result[k],
})).value(),
}
delete params.args.cursor
}
return await next(params)
})发布于 2021-12-31 04:07:26
发布于 2021-12-31 06:24:19
Prisma所称的游标分页,其他人称之为“键集”分页。不涉及实际的游标。但是它的效率将取决于查询的其余部分,以及是否有正确的索引(Es),这两个索引我们都不能用提供的信息来评估。既然您正在将所有数据读入内存中,那么为什么不直接读取它并省略分页呢?
https://stackoverflow.com/questions/70538263
复制相似问题