如何优化文件查询性能?能否将两次查询合并为单次请求?
合并两次数据库查询以提升性能的实现方案
当然可行,将两次查询合并为单次能减少数据库IO操作,有效提升接口性能。以下提供两种适配你需求的实现方案:
方案一:数据库层面完成排序(推荐)
通过调整查询的排序规则,让数据库直接返回「目录按字母升序排列在前,非目录按字母升序排列在后」的结果,无需在代码中额外处理分组与合并。
@Get('roots') async findRoots(@Req() request: Request) { const user = await this.authService.findCurrentUser(request); const allFiles = await this.fileService.findAll({ relations: ['user', 'parent', 'parent.parent'], order: [ // 强制目录排在最前面,不受字符串默认排序影响 Raw(alias => `CASE WHEN ${alias}.type = 'dir' THEN 0 ELSE 1 END`), // 同类型内按名称字母升序排序 { name: 'ASC' }, ], where: { user: user.user_id, parent: IsNull(), }, }); return allFiles; }
补充说明
- 若你的
type字段是枚举类型,且dir在枚举中的定义顺序本身靠前,可将Raw语句替换为{ type: 'ASC' },简化排序逻辑。 - 数据库层面排序能利用索引优化,数据量越大,相比内存排序的性能优势越明显。
方案二:内存中分组排序
一次性查询所有符合条件的文件,再在代码中过滤出目录和非目录,分别排序后合并。该方案无需依赖数据库排序逻辑,适合数据量较小的场景。
@Get('roots') async findRoots(@Req() request: Request) { const user = await this.authService.findCurrentUser(request); const allFiles = await this.fileService.findAll({ relations: ['user', 'parent', 'parent.parent'], where: { user: user.user_id, parent: IsNull(), }, }); // 过滤并排序目录 const directories = allFiles .filter(file => file.type === 'dir') .sort((a, b) => a.name.localeCompare(b.name)); // 过滤并排序非目录文件 const otherFiles = allFiles .filter(file => file.type !== 'dir') .sort((a, b) => a.name.localeCompare(b.name)); return directories.concat(otherFiles); }
注意事项
- 两种方案均只发起一次数据库请求,相比原代码减少了一次IO开销。
- 若使用方案二,需注意
localeCompare的区域设置,确保字母排序符合业务预期。
内容的提问来源于stack exchange,提问作者Ojix
相关产品推荐
相关产品推荐

