轉自:http://ju.outofmemory.cn/entry/61448python
關鍵詞:web
flask-sqlalchemy, sqlalchemy, 分表,分庫sql
大型系統、海量數據確定涉及到分庫分表這些提升效率的手段。因爲sqlalchemy的orm思想是一張表對應一個對象,那麼當咱們有N張相同結構只是表名有區別的分表,sqlalchemy orm怎樣處理呢。好比有以下表:flask
CREATE TABLE `goods_desc_0` ( `goods_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '商品id', `goods_desc` text NOT NULL COMMENT '商品詳細描述', PRIMARY KEY (`goods_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='商品信息詳情' CREATE TABLE `goods_desc_1` ( `goods_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '商品id', `goods_desc` text NOT NULL COMMENT '商品詳細描述', PRIMARY KEY (`goods_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='商品信息詳情'
class GoodsDesc(db.Model): __tablename__ = 'goods_desc' goods_id = db.Column(db.Integer, primary_key=True) goods_desc = db.Column(db.Text, default=None) def __str__(self): return "GoodsDesc => { \ goods_id:%d, goods_desc:'%s'}" % ( self.goods_id, self.goods_desc) __repr__ = __str__ # 代碼示例 goods_id = 101 table_index = goods_id%2 table_name = 'goods_desc_%d' % table_index GoodsDesc.__table__.name = table_name gd = GoodsDesc.query.filter(GoodsDesc.goods_id == goods_id).first() # 這樣寫雖然也能工做,可是是很是危險的,由於GoodsDesc.__table__是靜態全局變量, # 並且不是web程序request級別的,是app context的,很是不安全。
通過N次Google,終於找到解決方案,並且代碼寫起來也很優雅。代碼以下:安全
class GoodsDesc(object): _mapper = {} @staticmethod def model(goods_id): table_index = goods_id%100 class_name = 'GoodsDesc_%d' % table_index ModelClass = GoodsDesc._mapper.get(class_name, None) if ModelClass is None: ModelClass = type(class_name, (db.Model,), { '__module__' : __name__, '__name__' : class_name, '__tablename__' : 'goods_desc_%d' % table_index, 'goods_id' : db.Column(db.Integer, primary_key=True), 'goods_desc' : db.Column(db.Text, default=None), }) GoodsDesc._mapper[class_name] = ModelClass cls = ModelClass() cls.goods_id = goods_id return cls # 外部代碼調用如例以下: # ----------------------- # 新增插入 gdm = GoodsDesc.model(goods_id) gdm.goods_desc = 'desc' db.session.add(gd) # 查詢 gdm = GoodsDesc.model(goods_id) gd = gdm.query.filter_by(goods_id=goods_id).first()