uni-app 聚合操作下 match中添加过滤条件使用or后查询速度大大降低 优化建议
uni-app 聚合操作下 match中添加过滤条件使用or后查询速度大大降低 优化建议
产品分类:
uniCloud/支付宝小程序云
示例代码:
比如有一个数据库A,在一次请求的基础上需要查询两次,一次按照时间来查询30条数据,一个随机查询30条数据,然后重复请求两次,响应速度大大降低,然后合并在一个后用or,同样也会大大降低查询速度,这种之前在阿里云不会有这个问题,这个问题可以优化一下吗?
let res = await DB.collection('A').aggregate()
.match({
time: command.gt(time),
user: "ok",
})
.lookup({
from: 'user',
let: {
user_id: '$id',
},
pipeline: aggregate.pipeline()
match(command.expr(aggregate.and([
aggregate.eq(['$id', '$$user_id']),
])))
.project({
id: 1,
})
.done(),
as: "data_user",
})
.sample({
size: 30,
})
.end()
===========================================================================
let Res = await DB.collection('A').aggregate()
.match({
user: "ok",
})
.lookup({
from: 'user',
let: {
user_id: '$id',
},
pipeline: aggregate.pipeline()
match(command.expr(aggregate.and([
aggregate.eq(['$id', '$$user_id']),
])))
.project({
id: 1,
})
.done(),
as: "data_user",
})
.sample({
size: 30,
})
.end()
操作步骤:
如上面所说
预期结果:
速度提升
实际结果:
没有提升
bug描述:
聚合操作的下,在match中添加过滤条件时,使用了or后,查询速度大大降低,都是5、6秒后才会出结果,删除or只保留简单的过滤条件后变成一秒出结果,请问一下这能优化一下吗
理论上没有不会有这么大的区别。有具体的代码或者截图吗,可以发来看看
看截图
添加索引试下。
在uni-app中,当你使用聚合操作并在match
阶段添加过滤条件时,如果使用了$or
操作,确实可能会导致查询速度变慢。这主要是因为$or
操作需要数据库扫描多个索引或进行全表扫描来满足条件,从而增加了查询的复杂性。
为了优化这种情况,你可以考虑以下几种方法:
-
索引优化: 确保你的数据库字段已经建立了合适的索引。对于
$or
中的每个条件,如果可能的话,都应该尽量利用索引来加速查询。 -
减少查询字段: 在
match
阶段之后,使用project
阶段只选择你需要的字段,减少数据传输和处理的开销。 -
使用复合索引: 如果
$or
中的条件是多个字段的组合,考虑创建复合索引。复合索引可以显著提高多个字段组合查询的速度。 -
重构查询: 如果可能,尝试重构查询逻辑,避免使用
$or
,或者将其拆分成多个单独的查询,然后在应用层合并结果。
以下是一个使用MongoDB(假设你的uni-app后端使用的是MongoDB)的示例代码,展示了如何优化包含$or
的查询:
// 假设我们有一个集合users,并且需要查询满足以下条件的文档:
// 年龄大于30或者城市是'Beijing'
// 优化前:直接使用$or
db.users.aggregate([
{
$match: {
$or: [
{ age: { $gt: 30 } },
{ city: 'Beijing' }
]
}
},
{
$project: {
_id: 0,
name: 1,
age: 1,
city: 1
}
}
]);
// 优化后:创建复合索引并尝试拆分查询(如果逻辑允许)
// 首先,创建复合索引(如果尚未创建)
db.users.createIndex({ age: 1, city: 1 });
// 然后,考虑将查询拆分为两个单独的查询(如果业务逻辑允许)
// 在应用层合并结果
const query1 = db.users.aggregate([
{
$match: { age: { $gt: 30 } }
},
{
$project: {
_id: 0,
name: 1,
age: 1,
city: 1
}
}
]);
const query2 = db.users.aggregate([
{
$match: { city: 'Beijing' }
},
{
$project: {
_id: 0,
name: 1,
age: 1,
city: 1
}
}
]);
// 在应用层,你可以使用Promise.all或其他异步处理方法来合并这两个查询的结果
Promise.all([query1.toArray(), query2.toArray()])
.then(([results1, results2]) => {
const finalResults = results1.concat(results2);
// 处理finalResults
})
.catch(error => {
// 处理错误
});
请注意,以上代码示例是基于MongoDB的,如果你的uni-app后端使用的是其他数据库,可能需要调整查询语法和索引创建方式。