被 ORM 折磨, sql 1 分钟写好, ORM 想了一个小时,没写出来😭

2021-09-14 15:24:34 +08:00
 wuwukai007

救救孩子吧

select d.id,d.created_time,(select count(*) from word where word.dictionary_id=d.id)
    as word_count,
       (select account from user where user.id = d.creator_id) as username,
       d.dictionary_name
        from dictionary
    as d where d.thesaurus_name='professional'
6729 次点击
所在节点    Python
39 条回复
kevinonepiece
2021-09-14 20:21:01 +08:00
@cp19890714
@Thinklong 为啥要干掉连表查
cyrivlclth
2021-09-14 20:26:16 +08:00
@kevinonepiece 这次快了,请求多了,数据库遭不住。。。好多子查询。。。
ragnaroks
2021-09-14 21:41:01 +08:00
@Pursue9
linq 好像 csharp 独一家,不过转成方法的话基本上所有语言都有。
比如这样的语法 ↓
var ageList=table().select(e=>e.age).where(e=>e.age>18).list()
512357301
2021-09-14 22:20:53 +08:00
原始 SQL 的写法本质上还是 left join 吧,你的那个写法应该是 mysql 独有或者不算特别标准的写法,
你可以把那两个子查询从 select 那里挪到 from 后面,用 left join 关联,这样会不会更好用 orm 实现呢。
cp19890714
2021-09-14 22:25:59 +08:00
@kevinonepiece
以我个人的使用经验, 我觉得多次简单查询对比关联查询有以下好处:
* 有效使用数据库缓存
* 关联的表多了,且没有用好索引, 一次查询的时间就更长. 这种并发查询多了, 就会导致数据库压力骤增. 例如:一次查询要 100ms,那么在未来很可能成为慢查询,进而可能导致雪崩.
* 减少锁的竞争
* 尽量降低数据库压力, 毕竟数据库的扩容比服务器扩容难多了. 在开发时,就让 sql 足够简单, 未来一旦出现数据库瓶颈, 大部分的代码不用考虑 sql 优化了, 直接升级数据库吧.
* 随着数据量的增加, mysql 的执行逻辑也会变化. 虽然开发时不是慢查询,但以后可能就会变成慢查询.
但并不是所有的关联查询都拆分, 对于效率非常高的关联查询, 还是不要拆分.
crystom
2021-09-14 22:31:33 +08:00
做 olap 分析能连表就连表,跟 oltp 场景不同
Rocketer
2021-09-14 22:33:44 +08:00
不用死脑筋,.Net 程序员也不是非 linq 不可,复杂查询还是会用 sql 的。

问题是你这 sql 不敢直接在生产环境用,怕是要被 dba 打死的。
Mithril
2021-09-14 22:47:08 +08:00
你需要一个 Linq 。。。
hushao
2021-09-14 23:44:29 +08:00
你都用 sqlalchemy,并且 sql 都写好了,实在写不出 orm 直接执行 sql 语句就行啊,要求必须使用 orm 的另说。
iseki
2021-09-15 00:21:29 +08:00
一般 ORM 都支持 raw sql 的吧,ORM 不适合不 O 的场景,统计之类的就非常不 O,强用 ORM 就是给自己找不痛快
gjquoiai
2021-09-15 01:01:59 +08:00
我超喜欢 sqlalchemy 的,我来给你写:
d = dictionary.alias()
w = word.alias()
u = user.alias()
select(
d.c.id,
d.c.created_time,
select(func.count("*").label("word_count")).select_from(w).where(w.c.dictionary_id == d.c.id).subquery(),
select(u.c.account).where(u.c.id == d.c.creator_id).subquery(),
).select_from(d).where(d.c.thesaurus_name == "professional")
gjquoiai
2021-09-15 01:07:01 +08:00
@gjquoiai #31 似乎应该把 subquery 换成 scalar_subquery,如果找不到关联表的话再加一个 correlate (
yalin
2021-09-15 03:46:07 +08:00
sql 一时爽
thtznet
2021-09-15 08:58:35 +08:00
查询和命令分离,只是查询可以不用 ORM 直接运行 SQL 效率还高,命令涉及到领域持久化,用 ORM 比较适合。
jakehu
2021-09-15 10:58:54 +08:00
用这个呗,即集成了 SQLAlchemy Core,又可以用原生写法。一个字,好用
https://github.com/encode/databases
IvanLi127
2021-09-15 12:45:51 +08:00
从 orm 中提取表名字段名,然后拼接 sql 的时候用上这些值,重构还有希望
pythonee
2021-09-15 15:07:27 +08:00
@Rwing
@Pursue9

我就说,这种写法看着怎么这么爽
seakingii
2021-09-16 10:48:03 +08:00
复杂的查询可以建存储过程,再调用
NCZkevin
2021-09-16 15:39:09 +08:00
@jakehu 想咨询一下,databases 插入的时候值一定要是字典吗,网上搜 databases 这个词太容易搜到别的东西了,很难搜到相关的。官方例子是
```
values = [
{"text": "example2", "completed": False},
{"text": "example3", "completed": True},
]
```
能不能支持这种?
```
[
["example2",False] ,["example2",True]
]
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/801777

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX