zoukankan      html  css  js  c++  java
  • 【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

    从如上的CURD中,我们可以看到如下一段实时修改表名的代码

    // 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
    db dbQuerier
    isTx bool
    sharding func(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

     

    祝玩的开心~

  • 相关阅读:
    linux服务器git pull/push时提示输入账号密码之免除设置
    如何查看Linux发行版本
    pm2日志切割
    CentOS下配置redis允许远程连接
    Node.js对SQLite的async/await封装
    Linux 系统命令行下,对 SQLite3 数据库使用的一般操作
    CentOS 7下使用n工具更新Node.js
    英语原理,索引
    词根词缀,非核心prefix/suffix/root
    哲学家核心价值观
  • 原文地址:https://www.cnblogs.com/voipman/p/15589974.html
Copyright © 2011-2022 走看看