朋友要我帮忙做网站,自己的品牌怎么推广加盟,学校网站开发4人小组分工,做网站网站会怎么样1.需求及场景概述 现有系统中因历史数据量过大#xff0c;产生了将历史数据进行按月存储的要求#xff0c;系统和数据库交互使用的是sqlalchemy#xff0c;假设系统的原来的历史记录表#xff08;record#xff09;如下#xff1a; 为了将历史数据按月分表存储#xff0…1.需求及场景概述 现有系统中因历史数据量过大产生了将历史数据进行按月存储的要求系统和数据库交互使用的是sqlalchemy假设系统的原来的历史记录表record如下 为了将历史数据按月分表存储我们需要以此表为基础按月创建对应的月表来进行分表存储同时又要使用orm的功能。面对这样的需求我们很自然的会想到创建如下模型
class Recode_202405(Base): __tablename__ record_202405 id Column(INT(11), primary_keyTrue) 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, reflectTrue)
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(metadatamdata, namef{table_name}_{date})
try:# 创建表new_table.create(bindengine)
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 dbSQLALCHEMY_DATABASE_URL fmysqlpymysql://{mysql_user}:{parse.quote_plus(mysql_password)}{mysql_host}:{mysql_port}/{mysql_db}?charsetutf8engine create_engine(SQLALCHEMY_DATABASE_URL, pool_recycle7200)
SessionLocal sessionmaker(autocommitFalse, autoflushFalse, bindengine)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, dateNone):autobase automap_base()autobase.prepare(engine, reflectTrue)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(metadatamdata, namef{table_name}_{date})# new_table base_model.tometadata(metadatamdata, namef{table_name}_{date})try:# 创建表new_table.create(bindengine)except BaseException as e:# 忽略建表异常存在多进程同时建表情况忽略后刷新autobase再试print(e)Automap的映射虽然是自动的但是只有在启动的时候生效也就是说如果新建一个数据表而没有告诉Automap那这个表是找不到的。在实际使用中可以捕获AttributeError异常并再次调用AutoBase.prepare(engine, reflectTrue) 刷新映射关系。autobase automap_base()autobase.prepare(engine, reflectTrue)base_model getattr(autobase.classes, f{table_name}_{date})return base_modeldef get_table_model(table_name, dateNone):autobase automap_base()autobase.prepare(engine, reflectTrue)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(metadatamdata, namef{table_name}_{date})# new_table base_model.tometadata(metadatamdata, namef{table_name}_{date})try:# 创建表new_table.create(bindengine)except BaseException as e:# 忽略建表异常存在多进程同时建表情况忽略后刷新autobase再试print(e)Automap的映射虽然是自动的但是只有在启动的时候生效也就是说如果新建一个数据表而没有告诉Automap那这个表是找不到的。在实际使用中可以捕获AttributeError异常并再次调用AutoBase.prepare(engine, reflectTrue) 刷新映射关系。autobase automap_base()autobase.prepare(engine, reflectTrue)base_model getattr(autobase.classes, f{table_name}_{date})return base_model# 使用
Record database.get_table_model(record, 202406)ll Record(name1111)with database.session_maker() as db:db.add(ll)db.commit()ll db.query(Record).all()print(ll)
参考sqlalchemy分表操作 - 知乎