sqlalchemy 分表实现方案
1.需求及场景概述
现有系统中因历史数据量过大,产生了将历史数据进行按月存储的要求,系统和数据库交互使用的是sqlalchemy,假设系统的原来的历史记录表(record)如下:

为了将历史数据按月分表存储,我们需要以此表为基础按月创建对应的月表来进行分表存储,同时又要使用orm的功能。面对这样的需求我们很自然的会想到创建如下模型
class Recode_202405(Base): __tablename__ = 'record_202405' id = Column(INT(11), primary_key=True) name = Column(String(100, 'utf8mb4_unicode_ci'))
这样当然可以,但是我们不可能每月手动去创建这个模型,然后重启自己的服务,这明显有问题, 那如何解决呢,下面就介绍一种在这种场景下基于sqlalchemy实现的分表存储方案。
首先,我们对我们应用场景及需求进行一下描述:
1.我们有一张基础表,这个表作为我们创建月表的模板。
2.当有新数据需要入库时,我们将数据按月存储到当前月份的月表中,如果当月表不存在系统自动创建。
3.支持使用OMR方便数据存储及查询。
2.实现方案
既然要支持使用ORM ,我们势必要获取月表的model。sqlalchemy0.9.1版本推出了Automap,它可以自动映射数据库的表,通过数据表名映射model。大概的用法如下:
from sqlalchemy.ext.automap import automap_baseAutoBase = automap_base()# reflect the tables
AutoBase.prepare(engine, reflect=True)
tablename = "record_202405"
RecordDao = getattr(AutoBase.classes, tablename)
既然可以通过表名映射回model,那么现在的问题就是如何基于已有的基础表创建当月的月表,可以参考如下代码:
from sqlalchemy.ext.automap import automap_base
AutoBase = automap_base()table_name = 'record'
date = '202405'
# 基于基础表创建指定月份的月表
base_table = autobase.metadata.tables[table_name]
mdata = MetaData()
new_table = base_table.tometadata(metadata=mdata, name=f'{table_name}_{date}')
try:# 创建表new_table.create(bind=engine)
except BaseException as e:print(e)
基于上述方案,我们可以封装一个方法,该方法接收两个参数,一个是表名,一个是分表的月份,其实可以进行任何程度的分表,返回该表的model,通过sqlalchemy 的ORM 进行增删改查操作,整体代码如下:
from sqlalchemy import create_engine, MetaData
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.automap import automap_base
from urllib import parse
from contextlib import contextmanager
import timemysql_user = 'root'
mysql_password = 'root'
mysql_host = '127.0.0.1'
mysql_port = 3306
mysql_db = 'db'SQLALCHEMY_DATABASE_URL = f'mysql+pymysql://{mysql_user}:{parse.quote_plus(mysql_password)}@{mysql_host}:{mysql_port}/{mysql_db}?charset=utf8'engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_recycle=7200)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)@contextmanager
def session_maker():try:db: Session = SessionLocal()yield dbdb.commit()except Exception as e:print(e)db.rollback()finally:db.close()def get_table_model(table_name, date=None):autobase = automap_base()autobase.prepare(engine, reflect=True)print(autobase)base_model = Nonetry:base_model = getattr(autobase.classes, table_name)except Exception as e:print(e)return base_modelif date == None: # 不分表的情况return base_modelelse: # 分表的情况# 获取基础类base_table = autobase.metadata.tables[table_name]mdata = MetaData()new_table = base_table.tometadata(metadata=mdata, name=f'{table_name}_{date}')# new_table = base_model.tometadata(metadata=mdata, name=f'{table_name}_{date}')try:# 创建表new_table.create(bind=engine)except BaseException as e:# 忽略建表异常,存在多进程同时建表情况,忽略后刷新autobase再试print(e)'''Automap的映射虽然是自动的,但是只有在启动的时候生效,也就是说如果新建一个数据表,而没有告诉Automap,那这个表是找不到的。在实际使用中,可以捕获AttributeError异常,并再次调用AutoBase.prepare(engine, reflect=True) 刷新映射关系。'''autobase = automap_base()autobase.prepare(engine, reflect=True)base_model = getattr(autobase.classes, f'{table_name}_{date}')return base_modeldef get_table_model(table_name, date=None):autobase = automap_base()autobase.prepare(engine, reflect=True)print(autobase)base_model = Nonetry:base_model = getattr(autobase.classes, table_name)except Exception as e:print(e)return base_modelif date == None: # 不分表的情况return base_modelelse: # 分表的情况# 获取基础类base_table = autobase.metadata.tables[table_name]mdata = MetaData()new_table = base_table.tometadata(metadata=mdata, name=f'{table_name}_{date}')# new_table = base_model.tometadata(metadata=mdata, name=f'{table_name}_{date}')try:# 创建表new_table.create(bind=engine)except BaseException as e:# 忽略建表异常,存在多进程同时建表情况,忽略后刷新autobase再试print(e)'''Automap的映射虽然是自动的,但是只有在启动的时候生效,也就是说如果新建一个数据表,而没有告诉Automap,那这个表是找不到的。在实际使用中,可以捕获AttributeError异常,并再次调用AutoBase.prepare(engine, reflect=True) 刷新映射关系。'''autobase = automap_base()autobase.prepare(engine, reflect=True)base_model = getattr(autobase.classes, f'{table_name}_{date}')return base_model# 使用
Record = database.get_table_model("record", '202406')ll = Record(name="1111")with database.session_maker() as db:db.add(ll)db.commit()ll = db.query(Record).all()print(ll)
参考:sqlalchemy分表操作 - 知乎
相关文章:
sqlalchemy 分表实现方案
1.需求及场景概述 现有系统中因历史数据量过大,产生了将历史数据进行按月存储的要求,系统和数据库交互使用的是sqlalchemy,假设系统的原来的历史记录表(record)如下: 为了将历史数据按月分表存储࿰…...
QML进阶(十五) QML各种标准元素的用法
文章目录 文本图像控件TextTextInputTextFieldTextEditTextAreaImage按钮控件ButtonRadioButtonCheckBoxComboBox进度控制控件ProgressBarSlider...
【工具使用】快速实现Makefile模板的方法
一,简介 我们在使用gcc编译程序时,常常需要自己实现Makefile,那么如何快速的实现Makefile呢?这里把一些基本的操作整理成模板,供参考。 二,模板介绍 功能包含基本功能编译exe(包括调用其他算…...
Linux-信号执行
1. 信号什么时候被处理 当进程从内核态返回到用户态的时候,进行信号的检测和处理 什么内核态,什么又是用户态呢? 当进程在CPU上运行时,内核态:允许进程访问操作系统的代码和数据,用户态:进程只…...
在线听歌播放器 梨花带雨网页音乐播放器 网页音乐在线听 源码
最新梨花带雨网页音乐播放器二开优化修复美化版全开源版本源码下载 下 载 地 址 : runruncode.com/php/19749.html 梨花带雨播放器基于thinkphp6开发的XPlayerHTML5网页播放器前台控制面板,支持多音乐平台音乐解析。二开内容:修复播放器接口问题&am…...
免费生成证件照
分享分享,免费福利,欢迎大家来体验!!! 不知道你是不是会时不时有使用证件照需求,这一个小程序,可以生成常见尺寸的证件照,全程免费,有需要的可以动动小手,体…...
深入探索数据链路层:网络通信的基石
⭐小白苦学IT的博客主页⭐ ⭐初学者必看:Linux操作系统入门⭐ ⭐代码仓库:Linux代码仓库⭐ ❤关注我一起讨论和学习Linux系统❤ 前言 在网络通信的宏伟世界中,数据链路层扮演着至关重要的角色。它位于物理层和网络层之间,不仅直接…...
STM32使用L9110驱动电机自制小风扇
1.1 介绍: 该电机控制模块采用L9110电机控制芯片。该芯片具有两个TTL/CMOS兼容输入端子,并具有抗干扰特性:具有高电流驱动能力,两个输出端子可直接驱动直流电机,每个输出端口可提供750800mA动态电流,其峰值…...
C语言——队列的实现
队列按照先进先出(FIFO,First In First Out)的原则管理数据。这意味着最先进入队列的元素会被最先移出,类似于排队等候服务的情况。队列通常有两个主要操作:入队(enqueue),将元素添加…...
15-LINUX--线程的创建与同步
一.线程 1.线程的概念 线程是进程内部的一条执行序列或执行路径,一个进程可以包含多条线程。 2.线程的三种实现方式 ◼ 内核级线程:由内核创建,创建开销大,内核能感知到线程的存在 ◼ 用户级线程:线程的创建有用户空…...
【退役之重学Java】如何解决消息持续积压等问题
一、将读写数据库等耗时的操作,从消费者逻辑中抽取出来,专门部署机器去完成这部分操作。...
Linux下的SPI通信
SPI通信 一. 1.SPI简介: SPI 是一种高速,全双工,同步串行总线。 SPI 有主从俩种模式通常由一个主设备和一个或者多个从设备组从。SPI不支持多主机。 SPI通信至少需要四根线,分别是 MISO(主设备数据输入,从设备输出),MOSI (主设数据输出从设备输入),SCLK(时钟信号),CS/SS…...
【转载】数字化工厂规划蓝图报告
制造业进入到全新的数字化时代,需要构建新型智能工厂、数字化工厂与智能车间以助力传统产业智能制造升级,将新一代信息技术贯穿到设计、工艺、生产、物流等各个环节。目的是完善创新体系、提升产品质量、推行绿色制造、增强核心竞争力、发展现代化客户体…...
《基于GNU-Radio和USRP的雷达通信系统的实现》文献阅读
文章目录 前言一、摘要二、引言三、联合系统实施1、基本原理2、实验方案 四、软件设置1、发射机2、接收机 五、实验结果1、实验设置2、波形3、室内外对比4、不同参数的结果 六、结论七、参考文献八、论文自取九、阅读收获 前言 本文记录《基于GNU-Radio和USRP的雷达通信系统的实…...
Sealos急速部署生产用k8s集群
最近一段时间部署k8s全部使用sealos了,整体使用感觉良好,基本没有什么坑。推荐给大家。 使用 Sealos,可以安装一个不包含任何组件的裸 Kubernetes 集群。 最大的好处是提供 99 年证书,用到我跑路是足够了。不用像之前kubeadm安装…...
VTK数据的读写--Vtk学习记录1--《VTK图形图像开发进阶》
读和写操作是VTK可视化管线两端相关的类--Reader和Writer类 Reader:将外部数据读入可视化管线,主要步骤如下 s1:实例化Reader对象 s2:指定所要读取的文件名 s3:调用Update()促使管线执行 对应的Writer: s1:实例化Writer对象 s2输入要写的数据以及指定写入的文…...
Vue3专栏项目 -- 一、第一个页面(下)
一、Dropdown 组件(下拉菜单组件)编码 1、基本功能:展示出下拉按钮和下拉菜单栏的样式 我们可以通过bootstrap来实现这个下拉框,需要注意它这个只是有样式,是没有行为的 然后这个下拉按钮的文字展示是根据用户名称展…...
一栈走天下:使用HBuilderX高效搭建Uni-App微信小程序开发环境
一栈走天下:使用HBuilderX高效搭建Uni-App微信小程序开发环境 Uni-App与HBuilderX简介Uni-App基础HBuilderX介绍 环境搭建步骤步骤1:安装HBuilderX步骤2:创建Uni-App项目步骤3:配置微信小程序平台步骤4:预览与发布 代码…...
docker安装Debian:11 freeswitch1.10.5
文章目录 一、生成一个镜像二、切换一个镜像源为阿里源三、安装一些相关依赖和freeswitch3.1第一步:安装freeswitch-mod和下载所需的依赖项3.2 设置密钥3.3 安装freeswitch所需的依赖项3.4 报错3.4.1 报错13.4.2 报错23.4.3 报错3 四、运行4.1 通话三十秒自动挂断 一…...
c3 笔记6 认识css样式表
<link>与import应该如何选择?事实上,使用link与import链接外部样式文件的效果看起来是一样的,区别在于<link>是HTML标记而import属于CSS语法。<link>标记有rel、type与href属性,可以指定CSS样式表的名称,这样就…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
