gorm-sharding分表插件升级版
代码地址: GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别.解决了原生sharding的三个问题:1.不支持不带分表键的查询 2,不支持不同分表策略的配置 3.没有配置分表的自定义sql可能因为无法解析而发生异常
更新点
💡
原生gorm-sharding支持的功能有限,在公共包common中做了功能的扩展
- 本插件的gorm版本与现在的大部分服务一致v1.20.8,与原作者的不一致,避免版本冲突
- 原sharding解析sql用的sqlParse不一定能成功解析一些自定义的复杂sql,所以遇到解析不了的直接扔给gorm处理。如果涉及到分表的则需改成可以被sharding识别的标准gorm sql写法
- 原sharding本身不支持全表扫描,在此做了支持
- 原sharding不支持全表汇总查询,在此做了对count和sum的支持
- 原sharding不支持多分表配置不同分表策略,在此增加了配置接口
简要
Gorm Sharding 插件使用 SQL 解析器和替换将大表拆分为较小的表,将查询重定向到分片表。给您高性能的数据库访问。
Gorm Sharding 是一个高性能的数据库分表中间件。
它基于Conn层做SQL拦截、AST解析、分表路由、自增主键填充,带来的额外费用极小。对开发者友好、透明,使用上与普通SQL、Gorm查询无差别,只需要额外注意一下分表键条件。
注意事项
- 1.不要自己拼接sql会导致无法识别分表键,目前解析的是gorm条件表达式,而不是sql树(binaryTree),所以无法支持原生sql的分表 建议写法.where().orderby().limit().offset().find这样子
- 2.查询条件需要分表键,如果没有的话需要UnionFlag 配置为true才不会报错,但是会导致全表扫描,慎用
特征
- 非侵入式设计。加载插件,指定配置,一切就完成了。
- 快如闪电。没有基于网络的中间件,与 Go 一样快。
- 多种数据库(PostgreSQL、MySQL)支持。
- 集成主键生成器(Snowflake、PostgreSQL 序列、自定义等)。
快速上手
1. go mod引入
2. gorm插件加载
shardByOrderIdConf := gormsharding.Config{ShardingKey: "order_id",NumberOfShards: uint(shardingNumber),PrimaryKeyGenerator: gormsharding.PKCustom, PrimaryKeyGeneratorFn: func(_ int64) int64 {return 0},ShardingAlgorithm: func(value any) (suffix string, err error) {if orderId, ok := value.(string); ok {return fmt.Sprintf("_%04d", HashStr(orderId)%shardingNumber), nil}return "", errors.New("invalid orderId")},ShardingAlgorithmForUnion: func(tableId int) (suffix string, err error) {return fmt.Sprintf("_%04d", tableId), nil},UnionFlag: true,}db.Use(gormsharding.RegisterMultiConf(map[string]gormsharding.Config{"order": shardByOrderIdConf,}))
原始代码加载方式:
//分表中间件DBHandle.Use(sharding.Register(sharding.Config{ShardingKey: ShardingKey,NumberOfShards: ShardingNumber,//PrimaryKeyGenerator: sharding.PKMySQLSequence,PrimaryKeyGenerator: sharding.PKCustom,PrimaryKeyGeneratorFn: func(_ int64) int64 {return 0},}, ShardTablesByUid...))
dao层调用
尽量采用gorm的标准写法,避免使用原生sql,可能导致无法分表
示例代码
orm := dao.GetKpayDB()db := orm.DBHandle.Table("order")if order.Uid != 0 {db = orm.DBHandle.Table("uid_order")}getOrderCondition(order, db)db = db.Order(" create_tm desc ")if order.CurPage > 0 && order.PageSize > 0 {db = db.Limit(order.PageSize).Offset((order.CurPage - 1) * order.PageSize)}err = db.Find(&orders).Errorif err != nil && err != gorm.ErrRecordNotFound {_ = log.Error(nil, fmt.Sprintf("GetOrders error, err=%v", err))return}
工作原理
原理图
插件加载
Sharding实现了gorm接口
// Plugin GORM plugin interface
type Plugin interface {Name() stringInitialize(*DB) error
}
Initialize中执行了函数compile
参数预处理(分表主键算法、后缀处理)
Initialize中生成了gorm语句执行的钩子,switchConn主要处理双写的
func (s *Sharding) registerCallbacks(db *gorm.DB) {s.Callback().Create().Before("*").Register("gorm:sharding", s.switchConn)s.Callback().Query().Before("*").Register("gorm:sharding", s.switchConn)s.Callback().Update().Before("*").Register("gorm:sharding", s.switchConn)s.Callback().Delete().Before("*").Register("gorm:sharding", s.switchConn)s.Callback().Row().Before("*").Register("gorm:sharding", s.switchConn)s.Callback().Raw().Before("*").Register("gorm:sharding", s.switchConn)
}
sharding实现gorm的接口
type ConnPool interface {PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}
实现的接口中都会调用resolve的函数 (解决旧查询拆分为全表查询和分表查询)
配置参数说明
以下标红的是本包中新增的字段
- UnionFlag:
- 类型:布尔值
- 说明:表示是否启用联合查询标志。当为 true 时,即使没有分表键,也能够查询,但会扫描全表,需要注意性能问题。 建议配成false,暴露出没有分表键的查询
- DoubleWrite:
- 类型:布尔值
- 说明:表示是否启用双写功能。当启用时,数据将同时写入主表和分表中。
- ShardingKey:
- 类型:字符串
- 说明:指定用于分表的列名。例如,对于产品订单表,可以根据
user_id
来分表。
- NumberOfShards:
- 类型:无符号整数
- 说明:指定分表的数量,即分表的个数
- tableFormat:
- 类型:字符串
- 说明:指定分表的表名格式。在不重写ShardingAlgorithm 分表函数时,自动根据分表数量算出
- ShardingAlgorithm:
- 类型:函数
- 说明:指定用于生成分表后缀的算法函数。该函数根据传入的列值,生成对应的分表后缀。
- ShardingAlgorithmForUnion:
- 类型:函数
- 说明:与
ShardingAlgorithm
对应,用于处理全表扫描但无分表字段查询的情况。根据传入的表 ID,直接返回对应的分表后缀。
- ShardingSuffixs:
- 类型:函数
- 说明:生成所有分表后缀的函数,用于支持迁移器和生成主键。在compile插件的时候生成函数--根据函数ShardingAlgorithm拼接后缀
- ShardingAlgorithmByPrimaryKey:
- 类型:函数
- 说明:指定根据主键生成分表后缀的算法函数。当没有指定分表键时使用。
- PrimaryKeyGenerator:
- 类型:整数
- 说明:指定主键生成器算法,可选项有 PKSnowflake、PKPGSequence 和 PKCustom。
- PrimaryKeyGeneratorFn:
- 类型:函数
- 说明:指定生成主键的算法函数。当使用自动增量类似的生成器时,可以忽略
tableIdx
参数。PrimaryKeyGenerator为 PKCustom时,直接返回0表示不做处理,让mysql自动递增
相关文章:
gorm-sharding分表插件升级版
代码地址: GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充,带来的额外开销极小。对开发者友好、透明,使用上与普通 SQL、Gorm 查询无差别.解决了原生s…...
MoviePy(Python音视频开发)
音视频基础帧率、码率、分辨率视频格式H.264和H.265视频压缩算法 Moviepy常见剪辑类VideoFlieClipImageFlieClipColorClipTextClipCompositeVideoClipAudioFlieClipCompositeAudioClip 常见操作音视频的读入与导出截取音视频 音视频基础 帧率、码率、分辨率 体积(V…...
Spring中的FileCopyUtils:文件复制的利器与详解
1. 概述 在Spring框架中,FileCopyUtils是一个用于文件复制操作的实用工具类。它提供了一系列静态方法,简化了文件从输入流到输出流、从文件到文件等的复制过程。这些方法都基于NIO(New I/O)技术,提供了高效的文件复制…...
【操作系统】读者—写者问题python解析
一个数据问价或记录可以被多个进程共享,我们把只读该文件的进程称为“读者进程”,其他进程为“写者进程”。允许多个进程同时读一个共享对象,但不允许一个写者进程和其他写者进程或读者进程同时访问共享对象。即:保证一个写者进程…...
【driver5】调用堆栈函数,printk,动态打印,ftrace,proc,sysfs
文章目录 1.内核函数调用堆栈:4个函数2.printk:cat /proc/cmdline查看consolettyS03.动态打印:printk是全局的且只能设打印等级,动态打印可控制选择模块的打印,在内核配置打开CONFIG_DYNAMIC_DEBUG4.top&perf&…...
计算机毕业设计springboot基于vue电商抢购限时秒杀系统ch0h8
技术栈 ide工具:IDEA 或者eclipse 编程语言: java 数据库: mysql5.7以上版本 可选框架:ssmspringboot都有的 前端:vue.jsElementUI 详细技术:springbootSSMvueMYSQLMAVEN 数据库工具:Navicat/SQLyog都可以 开发工具 Ec…...
顺序表的实现(迈入数据结构的大门)(2)
目录 顺序表的头插(SLPushFront) 此时:我们有两个思路(数组移位) 顺序表的头删(学会思维的变换)(SLPopFront) 顺序表的尾插(SLPushBack) 有尾插就有尾删 既然头与尾部的插入与删除都有,那必然少不了指定位置的插入删除 查找…...
学习笔记:IEEE 1003.13-2003【POSIX PSE51接口列表】
一、POSIX PSE51接口列表 根据IEEE 1003.13-2003,整理了POSIX PSE51接口API(一共286个),每个API支持链接查看。详细内容参考下面表格: SN Module/_POSIX_宏 Function File 1 POSIX_C_LANG_JUMP(2) longjmp() &…...
《QT实用小工具·五十》动态增删数据与平滑缩放移动的折线图
1、概述 源码放在文章末尾 该项目实现了带动画、带交互的折线图,包含如下特点: 动态增删数值 自适应显示坐标轴数值 鼠标悬浮显示十字对准线 鼠标靠近点自动贴附 支持直线与平滑曲线效果 自定义点的显示类型与大小 自适应点的数值显示位置 根据指定锚点…...
【qt】核心机制信号槽(下)
这里写目录标题 自定义的信号自定义的槽自定义的信号和槽的结合使用信号和槽的断开总结: 自定义的信号 信号就是一个函数声明 前面咱们都用的qt组件自带的信号,接下来我们自己写一个信号。 信号只需要在前面加一个signals即可 这个函数不需要实现 参数传…...
C++ 基础 输入输出
一 C 的基本IO 系统中的预定义流对象cin和cout: 输入流:cin处理标准输入,即键盘输入; 输出流:cout处理标准输出,即屏幕输出; 流:从某种IO设备上读入或写出的字符系列 使用cin、cout这两个流对…...
八股文(C#篇)
C#中的数值类型 堆和栈 值类型的数据被保存在栈(stack)上,而引用类型的数据被保存在堆(heap)上,当值类型作为参数传递给函数时,会将其复制到新的内存空间中,因此在函数中对该值类型的修改不会影…...
【YOLOv9算法原理简介】
YOLOv9算法原理 单阶段检测器:YOLOv9延续了YOLO系列的单阶段检测器设计,即在单次前向传播中同时预测边界框和类别概率,这使得它能够实现快速的检测速度。通用高效层聚合网络(GELAN) :YOLOv9引入了一种新的模型架构GELAN,它通过高效的层聚合块和计算模块,以较小的参数量…...
2010NOIP普及组真题 2. 接水问题
线上OJ: 一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid1950 解法一、朴素模拟 核心思想: 朴素模拟: 1、先给每个b[i]水龙头分配一个人a[i],b[i] 表示水龙头的剩余时间。同时标记该水龙头为 used 使用中 2…...
ElementUI从unpkg.com完整下载到本地的方法 - 解决unpkg.com不稳定的问题 - 自建镜像站 - 不想打包只想cdn一下
方法 方法1)随便弄个文件夹,根据官网npm方法下载包,提取即可 npm i element-ui -S cd /node_modules/element-ui/ ls src 安装npm方法:https://nodejs.org/en 方法2)不推荐 - 在github中搜索对应的库zip包࿰…...
什么是BFF API
BFF(Backend For Frontend)API 是一种架构模式,旨在为特定的前端应用(如移动应用、桌面应用或网页应用)提供定制化的后端服务。通过这种方式,后端可以根据前端的具体需求和特性,提供最优化的数据…...
分享自己一篇在亚马逊云科技AWS官网发的Blog技术文章
小李哥在亚马逊AWS官网,作为第一作者发了自己的第一篇AWS Blog文章,也是自己今年在AWS官网的第11篇文章。文章主要内容是描述为出海的金融企业,搭建满足PCI-DSS合规、FIPS 140-2 Level 3安全标准的传输中数据加密云端方案,主要用于…...
封装长按触发事件的uniapp组件
简单说一下原理 首先介绍三个针对触摸屏设备的事件,分别是: touchstart:当手指触摸屏幕时触发,即触摸开始的时候;touchend:当手指离开屏幕时触发,即触摸结束的时候;touchcancel&am…...
Docker 安装的MySQL迁移数据库
1. 导出数据库 docker ps :查看数据库对应的 CONTAINER ID docker exec -it id /bin/bash : 进入到mysql的docker实例中 cd /usr/bin : 进入到bin目录 mysqldump -u root -p123456 study > /root/study_backup0509.sql :使用mysqldump备份库,注意密码与-p之间…...
算法训练Day28 | ● 122.买卖股票的最佳时机II ● 55. 跳跃游戏 ● 45.跳跃游戏II
122.买卖股票的最佳时机II class Solution { public:int maxProfit(vector<int>& prices) {vector<int> dp(2,0);dp[0] -prices[0];for(int i1; i<prices.size(); i){dp[0] max(dp[0], dp[1]-prices[i]);dp[1] max(dp[1], prices[i]dp[0]);}return dp[1]…...
Linux(openEuler、CentOS8)基于chrony企业内网NTP服务器搭建实验
一、知识点 chrony 是由 守护进程 chronyd 以及 命令行工具 chronyc 组成的 chronyd 在后台静默运行并通过 123 端口与时间服务器定时同步时间,默认的配置文件是 /etc/chrony.conf chronyc 通过 323 端口与 chronyd 交互,可监控 chronyd 的性能并在运…...
前端开发框架Vue
版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Vue概述 Vue.js(简称Vue)是由尤雨溪(Evan You)创建并维护的一款开源前端开发框架。Vue以其轻量级、易上手和高度灵活的特点&…...
Vue2中引入ElementUI
Vue中引入ElementUI 目录 Vue中引入ElementUI安装 全库导入main.py使用 仅引入样式文件main.py使用 安装 官方文档 npm i element-ui -S全库导入 main.py import ElementUI from element-ui;Vue.use(ElementUI)使用 <template> <div class"main">&l…...
华中科技大学雷达站部署
一:项目地址 GitHub - HUSTLYRM/HUST_Radar_2023: 华中科技大学狼牙战队 RoboMaster 2023赛季 雷达站 二:安装依赖 2.1创建虚拟环境 首先是程序是基于python3.8完成,所以创建虚拟环境的时候,选择3.8的虚拟环境 conda create -…...
小程序引入 Vant Weapp 极简教程
一切以 Vant Weapp 官方文档 为准 Vant Weapp 官方文档 - 快速入手 1. 安装nodejs 前往官网下载安装即可 nodejs官网 安装好后 在命令行(winr,输入cmd)输入 node -v若显示版本信息,即为安装成功 2. 在 小程序根目录 命令行/终端…...
labview技术交流-将时间字符串转换成时间格式
应用场景 我们在数据库中设计了datetime类型的字段,比如字段名就叫“保存时间”,当我们使用labview将表中数据读取出来后datetime类型的数据是以字符串的格式显示的。而我们想计算两条数据“保存时间”的间隔时间时,用字符串类型自然是没法计…...
算法提高之迷宫问题
算法提高之迷宫问题 核心思想:最短路问题 从(n-1,n-1)开始bfs 往前走一个就存入pre数组 之后再遍历pre数组输出 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 1010,M N*N;#define x first#def…...
泛微E9开发 通过点击按钮来复制选择的明细行
泛微E9开发 通过点击按钮来复制选择的明细行 复制明细行功能背景展示效果实现方法 复制明细行 功能背景 用户可以通过“复制明细”按钮来实现新增选择的明细行,并且新增明细行的数据跟选择的数据完全一样,具体操作如下图所示: 手动新增明细…...
sqlalchemy 分表实现方案
1.需求及场景概述 现有系统中因历史数据量过大,产生了将历史数据进行按月存储的要求,系统和数据库交互使用的是sqlalchemy,假设系统的原来的历史记录表(record)如下: 为了将历史数据按月分表存储࿰…...
QML进阶(十五) QML各种标准元素的用法
文章目录 文本图像控件TextTextInputTextFieldTextEditTextAreaImage按钮控件ButtonRadioButtonCheckBoxComboBox进度控制控件ProgressBarSlider...
网站怎样做301/百度快照入口
前言很多童鞋没有系统的Unity3D游戏开发基础,也不知道从何开始学。为此我们精选了一套国外优秀的Unity3D游戏开发教程,翻译整理后放送给大家,教您从零开始一步一步掌握Unity3D游戏开发。 本文不是广告,不是推广,是免费…...
做网站都用什么工具/万网域名注册官网阿里云
while循环与do while循环的区别如下:1、循环结构的表达式不同while循环结构的表达式为:while(表达式){循环体};do while循环结构的表达式为:do{循环体;}while (条件表达);。2、执行时判断方式不同while循环执行时只有当满足条件时…...
乐清企业网站建设/谷歌排名查询
往期精选● 架构师高并发高性能分布式教程(4000G)● 39阶段精品云计算大数据实战视频教程● 互联网技术干货视频教程大全【菜单为准】● 2017年8月最新Intellij IDEA全套视频教程● 程序员如何制作高质量的简历【视频简历】● 两套大型电商实战项目 ● 200本经典编程相关…...
青岛网站seo技巧/seo外链工具有用吗
一、Spring数据访问模板 Spring提供的数据访问模板,分别适用于不同的持久化机制。 模板类(org.springframework.*)用途jca.cci.core.CciTemplateJCA CCI连接jdbc.core.JdbcTemplateJDBC连接jdbc.core.namedparam.NamedParameterJdbcTemplate支…...
wordpress图片清理/成都网络推广外包公司哪家好
在前阵子项目改造中,需要利用先前的S7-200 PLC与ifix进行通讯,故而,在做好上位机后,在现场实际测试了下。通过CP243-1以太网模块,顺利与KEPWARE建立连接,其中当然也有些要点要注意: 1.在kepware…...
怎么知道网站的域名/微信营销推广
一,Mllib的数据格式 1,本地向量 本地向量是存储在本地节点上的,其基本数据类型是Vector,其有两个子集,分别是密集的与稀疏的,我们一般使用Vectors工厂类来实现。如: Vectors.dese(1.0,2.0,3.…...