Node.js主流ORM框架如何实现动态分表方案?

摘要:针对高并发、数据量大的场景,通常会考虑采用分库分表进行优化。在这篇文章,我们重点盘点一下Node.js主流ORM框架的动态分表方案
针对高并发、数据量大的场景,通常会考虑采用分库分表进行优化。在这篇文章,我们重点盘点一下Node.js主流ORM框架的动态分表方案: 分表规则 比如我们需要对订单表进行分表操作。可以根据实际业务需求设计分表规则,在这里,我们根据顾客Id取模动态生成表名。比如,拆分为16张表,顾客Id为129,对应的表名如下: const tableName = `Order_${129 % 16}`; // Order_1 TypeORM 在TypeORM中可以按照如下方式设置动态表名: // 获取repository const repositoryOrder = dataSource.createQueryBuilder().connection.getRepository(EntityOrder); // 设置动态表名 const userId = 129; const tableName = `Order_${userId % 16}`; repositoryOrder.metadata.tablePath = tableName; // 查询订单 const orders = await repositoryOrder.find(); Drizzle ORM schema.ts const orderFactory = userId => pgTable( `Order_${userId % 16}`, { id: serial('id').primaryKey(), name: text('name').notNull(), }, ); export const order0 = orderFactory(0); ... export const order15 = orderFactory(15); query.ts import * as schema from './db/schema'; const db = drizzle(process.env.DATABASE_URL!, { schema }); const userId = 129; const modelName=`order${userId % 16}`; const orders = await db.query[modelName].findMany(); Prisma ORM Prisma ORM对动态表名的支持还在规划当中,参见:Table Partitioning 作为备选方案,我们可以使用$queryRawUnsafe直接构造原始SQL: const userId = 129; const tableName = `Order_${userId % 16}`; const orders = await prisma.$queryRawUnsafe(`SELECT * FROM "${tableName}"`); Vona ORM Vona ORM提供了两种模式:自动模式/手工模式 1. 自动模式 model/order.ts import { EntityOrder } from '../entity/order.ts'; @Model({ entity: EntityOrder, table(ctx: VonaContext, defaultTable: keyof ITableRecord) { const user = ctx.app.bean.passport.getCurrentUser(); if (!user) return defaultTable; return `${defaultTable}_${Number(user.id) % 16}`; }, }) export class ModelOrder {} defaultTable: 是在EntityOrder中定义的缺省表名,如:Order service/order.ts class ServiceOrder { async findAll() { return await this.scope.model.order.select(); } } 2. 手工模式 service/order.ts class ServiceOrder { async findAll() { const user = this.bean.passport.getCurrentUser(); const tableName = `Order_${Number(user!.id) % 16}`; const modelOrder = this.scope.model.order.newInstance(undefined, tableName as any); return await modelOrder.select(); } } newInstance: 第一个参数可以传入数据源,从而实现分库能力。这里忽略,因此传入undefined