【Golang】基于beego/orm实现相同表结构不同表名的分表方法实现
一、背景
在业务场景开发的过程中, 随着数据量的增加,相同表结构不同表名的分表策略是常用的方案选择之一。如下以golang做为后端业务开发,尝试修改beego的orm库做一个相同表结构不同表名的分表实现。
二、orm相同表结构不同表名的修改逻辑
文章图片
三、orm分表对比
操 作 |
不分表代码使用 | 分表代码使用 |
写 入 |
o := orm.NewOrm() user := User{Name: "slene"} // insert id, err := o.Insert(&user) |
o := orm.NewOrm() user := User{Name: "slene"}// set table name to `user_1` o.ShardingTable( func(tableName string) string { return tableName + "_1" }, )// insert id, err := o.Insert(&user) |
更 新 |
o := orm.NewOrm() user := User{Name: "slene"}// update user.Name = "astaxie" num, err := o.Update(&user) |
o := orm.NewOrm() user := User{Name: "slene"}// set table name to `user_1` o.ShardingTable( func(tableName string) string { return tableName + "_1" }, )// update user.Name = "astaxie" num, err := o.Update(&user) |
查 询 |
o := orm.NewOrm() user := User{id: 1}// select o.QueryTable(user).One(&user) |
o := orm.NewOrm() user := User{id: 1}// set table name to `user_1` o.ShardingTable( func(tableName string) string { return tableName + "_1" }, )// select o.QueryTable(user).Offset(offset).Limit(limit).One(&user)// select id, name from user_1 where id=1 limit 0,1 |
删 除 |
o := orm.NewOrm() user := User{id: 1}// delete o.Delete(user)// delete from user_1 where id=1 |
o := orm.NewOrm() user := User{id: 1}// set table name to `user_1` o.ShardingTable( func(tableName string) string { return tableName + "_1" }, )// delete o.Delete(user)// delete from user_1 where id=1 |
// set table name to `user_1` o.ShardingTable( func(tableName string) string { return tableName + "_1" }, )
我们一步步分析一下orm是如何实现表名的实时修改。
四、分表实现分析 4.1 修改代码文件:https://github.com/gityf/orm/blob/master/orm/types.go
// Ormer define the orm interface
type Ormer interface {
// ...
// set sharding table in time for different table name with same struct.
// ormer.ShardingTable(
//func(tableName string) string {
//return tableName + "_" + tableNameSuffix
//},
// )
ShardingTable(func(string) string)
}
修改types.go的Ormer接口,增加分表的函数,参数是一个获取分表的函数,即每一个分表的表名的设置是一个orm实例。通过orm.NewOrm()创建。
4.2 修改代码文件:https://github.com/gityf/orm/blob/master/orm/orm.go
修改orm.go文件,给结构orm增加如下两个分表相关的函数
type orm struct {
alias *alias
dbdbQuerier
isTxbool
shardingfunc(string) string
shardingTable func(string) string
}
有了如上的sharding函数,我们只要在创建orm时,实时的设置这个sharding函数,通过函数获取新表名。
在函数NewOrm中给新创建的
o := new(orm)
设置一个分表函数如下
// switch to another registered database driver by given name. func (o *orm) Using(name string) error { // ... if al, ok := dataBaseCache.get(name); ok { o.sharding = func(table string) string { if o.shardingTable == nil { return table } return o.shardingTable(table) } } // ... }
orm结构体有了分表函数的设置,我们需要给orm的成员dbQuerier增加分表函数如下
o.db = &DB{
RWMutex: al.DB.RWMutex,
DB: al.DB.DB,
stmtDecorators: al.DB.stmtDecorators,
sharding: o.sharding,
}
4.3 修改代码文件:https://github.com/gityf/orm/blob/master/orm/db_alias.go
DB是dbQuerier接口的一个实现,对DB结构体的实现增加分表函数
func (d *DB) Sharding(table string) string {
return d.sharding(table)
}
4.4 修改代码文件:https://github.com/gityf/orm/blob/master/orm/db.go
对db代码文件中的dbBase的CURD中的sql生成时,增加如下实时修改表名的实现 q.Sharding(mi.table)
// create insert sql preparation statement object.
func (d *dbBase) PrepareInsert(q dbQuerier, mi *modelInfo) (stmtQuerier, string, error) {
Q := d.ins.TableQuote()
// ...
query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s)", Q, q.Sharding(mi.table), Q, Q, columns, Q, qmarks)
// ...
}
其他的orm转sql的通过dbQuerier的q.Sharding(mi.table)获取表名
增加orm相同表结果不同表名的代码实现:https://github.com/gityf/orm
【【Golang】基于beego/orm实现相同表结构不同表名的分表方法实现】祝玩的开心~
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长