












ORM,全称是Object-relational mapping,即对象关系映射,借助ORM可以把类和数据库表(schema)对应起来。
我想大家手头上都不会少了ORM这个工具,借助ORM,我们可以以面向对象的方式来写SQL,例如:
session.query(User).where(cls.id == 1).order_by(id.desc()).first()
就相当于
SELECT * FROM user WHERE id == 1 ORDER BY id DESC LIMIT 1
对于SQL生手来说,ORM的方式更容易让人理解。
使用ORM的原因莫过于这么几个:
if...elif...else... 追加查询条件,如果用SQL写,就比较麻烦但是ORM也有很大的弊端,那就是:
UPDATE/DELETE/INSERT 语句,只有 MS SQL Server 支持 with_hint
操作,而 MySQL/PG/SQLite 都只能使用 prefix_with,但是如果你想要对 UPDATE/DELETE 使用数据库索引提示,则是无法实现的,只能
裸写SQL。也就是说,ORM虽然号称跨数据库,其实效果并不好,很多数据库的细节并不能覆盖。SELECT user.id, user.name, user.age ... 等,把 user 的所有属性
都查出来,当然,我们手写的 SELECT * 也差不多,这都属于浪费行为,对于一个小型数据库系统,这当然是没有问题,但是数据量一旦达到
亿行的级别,浪费就比较大了。所以其实我们需要的是一个能轻松防注入,能自行映射类和数据库表,能轻松写SQL的工具,Python中,SQLAlchemy仍然是首选,Golang中 我倒是认为sqlx能胜任。
我经常在ORM中这样写:
class BaseMixin:
id = Column(Integer, primary=True)
created_at = Column(Datetime, index=True)
updated_at = Column(Datetime, index=True)
deleted_at = Column(Datetime, index=True)
Go中也是类似的。对于数据量小的系统来说,上面的写法无所谓,但是对于数据量大的系统来说,每一个地方都可能是性能瓶颈。上面的写法 有这么几个缺点:
created_at 不应该加索引,对于没有水平分表的系统来说,id是连续自增的(即便分了,也是自增的,不过这个时候就要根据具体场景
来判断是否可以这么做了),因此不需要多加 created_at 这个索引deleted_at 的类型不应该是时间,且不应该单独加索引,deleted_at 一般是用来做软删除,记录删除时间是没有必要的,因为有
updated_at,而将其改为 Booleanl 类型之后,索引更是没有必要,因为区分度特别低,不是True就是False。正确的方式应该是根据
查询条件,结合前置条件做联合索引。Mixin 或者继承来写基类,不过前两点改造完成之后,倒也的确能够适用于99%的系统。参考资料:
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。