Gorm Sharding
Gorm Sharding 是一个高性能的数据库分表中间件。
它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别,只需要额外注意一下分表键条件。
安装
go get -u gorm.io/sharding
测试表结构
// ProjectLog 结构体
type ProjectLog struct {
global.GVA_MODEL
ID int64 `gorm:"primarykey"` // 主键ID
ProjectId int64 `json:"project_id" form:"project_id" gorm:"column:project_id;comment:;"`
UpdateContent datatypes.JSONType[project.Project] `json:"update_content" form:"update_content" gorm:"type:json;column:update_content;comment:;"`
UpdateContent2 datatypes.JSONType[project.Project] `json:"update_content2" form:"update_content2" gorm:"-"`
ParentId int64 `json:"parent_id" form:"parent_id" gorm:"column:parent_id;comment:;"`
}
// TableName ProjectLog 表名
func (p ProjectLog) TableName() string {
return "project_log"
}
迁移生成测试表
import (
"fmt"
"strconv"
"testing"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func TestMigrate(t *testing.T) {
mysqlConfig := mysql.Config{
DSN: "root:123456@tcp(127.0.0.1:3306)/admin_project?charset=utf8mb4&parseTime=True&loc=Local", // DSN data source name
DefaultStringSize: 191, // string 类型字段的默认长度
SkipInitializeWithVersion: false, // 根据版本自动配置
}
DB, err := gorm.Open(mysql.New(mysqlConfig))
if err != nil {
fmt.Println(err.Error())
return
}
//生成128张project_log表,具体数量看自己需要了。
for i := 0; i < 128; i++ {
tableName := fmt.Sprintf("project_log_%0*d", 3, i) //表名
DB.Table(tableName).AutoMigrate(&project_log.ProjectLog{})
}
}
配置 Sharding 中间件,为需要分表的业务表定义他们分表的规则
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/sharding"
)
mysqlConfig := mysql.Config{
DSN: "root:123456@tcp(127.0.0.1:3306)/admin_project?charset=utf8mb4&parseTime=True&loc=Local", // DSN data source name
DefaultStringSize: 191, // string 类型字段的默认长度
SkipInitializeWithVersion: false, // 根据版本自动配置
}
DB, err := gorm.Open(mysql.New(mysqlConfig))
DB.Use(sharding.Register(sharding.Config{
ShardingKey: "company_id",
NumberOfShards: 128,
PrimaryKeyGenerator: sharding.PKSnowflake,
}, "project_log"))
//创建数据
DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 1})
DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 2})
DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 3})
DB.Create(&project_log.ProjectLog{Company_id: 1, ParentId: 4})
依然保持原来的方式使用 db 来查询数据库。 你只需要注意在 CURD 动作的时候,明确知道 Sharding Key 对应的分表,查询条件带 Sharding Key,以确保 Sharding 能理解数据需要对应到哪一个子表。
//查询数据
var data []project.ProjectLog
DB.Unscoped().Select("company_id,parent_id").Where("company_id = ?", 1).
Where("parent_id IN ?", []int{1, 2, 3, 4}).Find(&data)
for _, v := range data {
fmt.Printf("公司Company_id: %d,Parent_id: %d \n", v.Company_id, v.ParentId)
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
我想问一个问题,这个方式的分表是,逻辑分表,还是实际分表