关于分页只能写 sql 的痛苦

2022-08-06 01:59:20 +08:00
 garyxi24
由于现在公司项目都是在数据库分页,只能写 sql 实现而且只能是一条 sql 。本人是个 sql 菜鸡,简单筛选还好说,复杂逻辑筛选用 sql 写就很痛苦,好不容易怼出来 sql 像💩一样,又臭又长,同样的逻辑如果内存分页比如用 java 去实现就可以很清晰、很舒服。
所以我是想请教一下有什么更好的分页方式,摆脱写 sql 的噩梦,上 es Hadoop spark flink 这些大数据生态组件?
6574 次点击
所在节点    MySQL
61 条回复
totoro52
2022-08-06 16:31:37 +08:00
@garyxi24 我可以跟你说一下我的解决方案:
数据存两份,一份存 ES ,一份存 mysql ,并且同步存( ES 有延迟问题)
存进数据库时是有关系的,中间表这些全部按照范式设计,而 ES 则作为宽表使用,所有的关联信息一起写进 doc 中
引发的问题:
关联表数据更新,ES 宽表字段没更新
解决方案:
引入 canal ,监听数据库改动,动态更新 ES 数据
目前系统已上线,经过改造整体查询数据比起数据库上升几十倍
totoro52
2022-08-06 16:35:17 +08:00
@garyxi24 还有很多大厂禁止多表 JOIN ,有的甚至直接禁止 JOIN ,但有些场景必须使用关联,所以其实很多大厂都会自己的检索系统
idragonet
2022-08-06 16:51:04 +08:00
用 ORM 还需要什么自己写分页
100Percent
2022-08-06 17:19:38 +08:00
@liaohongxing #10 建议你放弃编程,连百万年薪都赚不到
LeegoYih
2022-08-06 17:44:48 +08:00
@garyxi24 应该在设计的时候就避免这种情况发生,可以设计为:
- 如果 b 服务中的数据是长期不变的,可以在 a 服务中冗余一些数据
- 如果 a 和 b 服务是属于同一种业务,那么就不应该拆分为两个服务
- 如果以上都不满足,大概率是需求或者设计有问题了,可以考虑用妥协的方案,比如:伪分页(不展示总数)、滚动搜索(不支持跳页,只能一页一页翻)

PS:实际上 es 的分页性能比数据库差很多,有分页需求肯定是不适合的,通常只用滚动搜索。
liaohongxing
2022-08-06 17:55:21 +08:00
@100Percent 我为我说话有些戾气道歉 ,我看贴之前楼主没有那么多补充说明,没有提到微服务等场景, 这标题也起的有问题,但是万变不离其宗,离开 SQL 很难弄 ,引入 ES 组件在微服务多条件,多服务聚合场景下,去用 ES, 涉及到的数据同步, 多服务联合,多服务数据聚合,复杂度增加 500%
wangxiaoaer
2022-08-06 17:55:23 +08:00
@LeegoYih #7 很好奇现在的业务不用 join 的话,关联查询如何做? 几百万条数据总不能分别查出来,程序里面自己做匹配吧
wangxiaoaer
2022-08-06 17:59:29 +08:00
@garyxi24 #27 这种情况我的理解是:

1 这样的微法就是瞎捷豹微,服务拆分不一定合理。

2 如果必须这么做,弄个统计库,把需要的表都同步过去。但如果应用本身已经分表分库,数据量可能很大了,这个统计库可能同步成本比较高。
garyxi24
2022-08-06 20:34:14 +08:00
@EminemW 也不是每个字段都要筛选哈,只是会有筛选条件复杂的情况。至于报表我觉得是另一条路线,实时性要求不那么高,可以搭建数仓,查起来方便一些。
dk7952638
2022-08-06 22:41:25 +08:00
只有 Java 才能救编程!
yogogo
2022-08-06 23:10:36 +08:00
@garyxi24 #49 可以用 JPA 的 Specification ,多条件筛选,join 多表查询很好用
bzj
2022-08-06 23:55:24 +08:00
我想了半天内存分页是啥玩意,怎么说呢,又菜又爱抱怨
zhaozs1
2022-08-07 06:39:30 +08:00
另外想跟大家探讨一个 sql 问题,比如我有一张 user 用户表、一张 role 权限表、还有一张 user_role 用户权限关联表,我现在想筛出至少有一种权限不存在的 user ,有什么好的 sql 实现?
select * from user u
where
(
not exsists ( select ur.roleid from user_role ur where ur.userid = u.id)
or
not exsists ( select ua.uaid from user_admin ua where ua.userid = u.id)
)
cnoder
2022-08-07 10:10:10 +08:00
你这查起来这么痛苦是因为数据库没设计好
garyxi24
2022-08-07 17:32:04 +08:00
@yogogo 子查询呢,支持的怎么样
garyxi24
2022-08-07 17:34:17 +08:00
@zhaozs1 user_admin 什么意思,另添加的一张表代表拥有所有权限吗?
garyxi24
2022-08-07 17:37:33 +08:00
@cnoder 并不是这样哈,本人是做 tob 的,像 erp 这种数据库设计表之间的关联很多,是会非常复杂的。
garyxi24
2022-08-07 17:57:36 +08:00
@LeegoYih 嗯,拿我之前的公司举例,主做企业管理系统这块,模块很多,比如项目管理、客户关系管理、计划管理,都会拆成一个个服务。当然,一般情况下,各模块功能相对独立,不会出现那种情况,但像一些基础数据,比如主数据模块里的客户数据、物料数据,是会被其他模块依赖的,所以可能会出现那种情况。
yogogo
2022-08-07 22:41:12 +08:00
@garyxi24 #55 子查询还没试过,我也是因为要写那么长的 SQL 语句才开始使用 Specification
vone
2022-08-08 09:46:18 +08:00
@garyxi24 根据我的经验,分页实际开发人员偷懒的做法。

举个例子,假设某个业务,数据总量为 1000 行,如果 50 行分一页则需分 20 页。分页只是简单粗暴数据切分,并没有业务上的依据,对业务的操作的人员来说,第 1 页的重要性和第 20 页的重要性几乎一样。


所以为什么要分页?答案:因为开发人员无法解决一次性查询全量数据的性能问题。

业务人员真的需要分页?答案:不需要,谁也不想一页一页点 20 次。

当业务人员的查询条件对应的数据有 1000 行时,他实际想干什么? 答案:他可能真的是想一次性看 1000 行数据。


如果不使用分页,只根据实际业务进行限制则会有以下做法:
1 、默认数据限制起止时间,如默认只显示最近 7 天,但提供:最近一月、最近一季度、全部时间、自定义时间的切换选项
2 、默认只显示需要处理的数据状态,如默认不显示已完成、已删除、已作废,但是提供可以查询全部状态的选项
3 、默认只显示我负责、待我处理的数据内容
4 、根据业务重要性做排序,把最需要展示、处理的放在最上面
5 、增加一个总行数输入框,限制默认的最大数据量,但可以修改(如:1000 行)

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

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

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

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

© 2021 V2EX