Vona ORM分表全攻略
分表
針對高并發、數據量大的場景,通常會考慮采用分表機制進行優化。下面以 Model User/Order 為例,通過查詢用戶的訂單列表,來演示分表的使用方法
分表規則
比如需要對訂單表進行分表操作。可以根據實際業務需求設計分表規則,在這里,根據用戶Id取模動態生成表名。比如,拆分為16張表,用戶Id為129,對應的表名如下:
const tableName = `Order_${129 % 16}`; // Order_1
準備Models
先準備兩個 Models:User/Order
- Model Order
@Model({
entity: EntityOrder,
})
class ModelOrder{}
- Model User
@Model({
entity: EntityUser,
relations: {
orders: $relation.hasMany(() => ModelOrder, 'userId'),
},
})
class ModelUser {}
查詢數據
1. 直接查詢訂單列表
class ServiceOrder {
async selectOrdersDirectly() {
const userId = 129;
const orders = await this.scope.model.order.select({
where: {
userId,
},
});
}
}
到目前為止,使用默認表名查詢userId=129的訂單列表
2. 基于關系查詢訂單列表
class ServiceOrder {
async selectOrdersByRelation() {
const userId = 129;
const userAndOrders = await this.scope.model.user.get({
id: userId,
}, {
include: {
orders: true,
},
});
}
}
到目前為止,使用默認表名查詢userId=129的用戶信息,使用默認表名查詢該用戶的訂單列表
使用分表:動態方式
可以在代碼中動態使用分表:
class ServiceOrder {
async selectOrdersDirectly() {
const userId = 129;
+ const tableName = `Order_${userId % 16}`;
+ const modelOrder = this.scope.model.order.newInstance(undefined, tableName as any);
const orders = await modelOrder.select({
where: {
userId,
},
});
}
}
newInstance: 傳入要使用的表名,返回新的 Model 實例
到目前為止,使用分表查詢userId=129的訂單列表
使用分表:Relation動態選項
可以在 relation 選項中動態指定表名:
class ServiceOrder {
async selectOrdersByRelation() {
const userId = 129;
+ const tableName = `Order_${userId % 16}`;
const userAndOrders = await this.scope.model.user.get({
id: userId,
}, {
include: {
orders: {
+ meta: {
+ table: tableName as any,
+ },
},
},
});
}
}
meta.table: 指定 relationorders要使用的表名
到目前為止,使用默認表名查詢userId=129的用戶信息,使用分表查詢該用戶的訂單列表
使用分表:Model配置
也可以直接在 Model 中配置分表規則,從而簡化查詢代碼
- Model Order
@Model({
entity: EntityOrder,
+ table(_ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) {
+ const userId = where?.userId;
+ if (!userId) return defaultTable;
+ return `Order_${Number(userId) % 16}`;
+ },
})
class ModelOrder{}
table: 指定函數,實現分表規則
- 查詢數據
現在,又可以使用常規的方式查詢用戶的訂單列表
class ServiceOrder {
async selectOrdersDirectly() {
const userId = 129;
const orders = await this.scope.model.order.select({
where: {
userId,
},
});
}
}
class ServiceOrder {
async selectOrdersByRelation() {
const userId = 129;
const userAndOrders = await this.scope.model.user.get({
id: userId,
}, {
include: {
orders: true,
},
});
}
}
使用分表:App Config配置
也可以在 App config 中配置 Model options:
src/backend/config/config/config.ts
// onions
config.onions = {
model: {
'test-vona:order': {
table(_ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) {
const userId = where?.userId;
if (!userId) return defaultTable;
return `Order_${Number(userId) % 16}`;
},
},
},
};
于是,也可以使用常規的方式查詢用戶的訂單列表
使用分表:Relation靜態選項
也可以在定義 Relation 時指定靜態選項:
@Model({
entity: EntityUser,
relations: {
orders: $relation.hasMany(() => ModelOrder, 'userId', {
+ meta: {
+ table(_ctx: VonaContext, where: EntityOrder | undefined, defaultTable: keyof ITableRecord) {
+ const userId = where?.userId;
+ if (!userId) return defaultTable;
+ return `Order_${Number(userId) % 16}`;
+ },
+ },
}),
},
})
class ModelUser {}
同樣,也可以使用常規的方式查詢用戶的訂單列表
Vona ORM已開源:github.com/vonajs/vona

針對高并發、數據量大的場景,通常會考慮采用分表機制進行優化。下面以 Model User/Order 為例,通過查詢用戶的訂單列表,來演示分表的使用方法
浙公網安備 33010602011771號