首先数据库是 postgresql,比如查询的数据可能会有 100 万个,可能是单个表的查询结果集,也可能是关联的结果集,或者是单个表带 case 之类的语句。查询的结果集会直接在 postgresql 转换成 Json 数组字符串
( 1 ) 100 万个数据,不可能全部都能在 ui 展示的,首先想到的是一种比较简单分页策略,即只有上一页,下一页,跳转目标页的功能,不查询最大页数和最大数据量,依据数据库的 limit 的 start (位置)和 number (数据量)来搞分页。这个分页策略有一个开发问题,就是前端和后端要配合好查询那部分的接口参数
( 2 )还有一种分页策略,是 element 的官网推荐的,分页处理方式:将全部的数据拿出来之后再进行分页,例如把 100 个万数据全部拿到前端,但不全部展示,分页由前端的来搞,这个分页策略,可以查询最大数据量,最大页数。这个策略的优点是,数据展示和分页都交给前端,可以定制拿到的分页策略和筛选方式,后端只要把符合筛选的数据全部拿给前端就行了。
这两种分页策略,哪类场景比较适合?是后面第二个比第一个综合来看更合适吗?
还有哪些其他的策略了?
1
815979670 2019-12-18 09:04:11 +08:00 1
首先 把 100W 数据全部展示出来这个需求绝对有问题,就算是给你一个 excel100w 行的文件 你也不会每一行去逐行看
|
2
sikariba 2019-12-18 09:07:30 +08:00
后面这种方案实现起来容易些,但性能肯定很差的。别说 100w 了,1w 都够呛吧
|
3
tonytonychopper 2019-12-18 09:08:41 +08:00 via Android
没遇到分页前端来做的情况。而且你一次只显示一页,根本不需要全部给前端,况且有 100w 条。
|
4
tctc4869 OP @815979670 可能是我用词问题吧,100 个数据不可能全部展示的,只是说的是一个分页策略问题。是由后端只给数据,前端定制分页,还是由后端定制分页,前端只负责传页码和数据量
|
5
itstudying 2019-12-18 09:10:56 +08:00
大多都会选择第一种吧,第二种当并发变大时服务和带宽压力会很大,而且真正需要全部数据的用户也没那么多。
|
6
tctc4869 OP @tonytonychopper
@sikariba element 好像推荐过这种分页策略,在 element 的官网提供的分页处理方式:将全部的数据拿出来之后再进行分页。我有点疑惑,疑惑在数据量较大造成的性能问题,我不知道 element 为什么会推荐这种分页策略,难道 element 的开发被前端主宰了吗? |
7
815979670 2019-12-18 09:11:21 +08:00
@815979670 第一种 对前端来说压力不大 对后端来说处理数据不多 压力也不会大(主要看你的数据复杂程度)
或者两者结合一下 在第二种的基础上做一个懒加载翻页? |
8
Alexhohom 2019-12-18 09:11:39 +08:00
肯定是后端分页啊,前端处理不了这么多数据,可以做一个平滑下一页,滚轮拖到一定位置,前端去请求下页内容。
|
9
evilhero 2019-12-18 09:18:50 +08:00 via Android
假设加载 1000 条数据耗时 1 秒
那么加载 100w 条约等于 1.9 小时… 把 100w 条数据扔到前端 |
10
AreYou0k 2019-12-18 09:19:28 +08:00
element 给的数据多大, 你的多大. 这个要看数据量吧, 而且它只是一个 demo 而已,没说推荐这种方式
|
11
zhzbql 2019-12-18 09:24:49 +08:00
前端分页肯定是数据量小的情况,几千上万条顶天了。100w 条数据还用前端分页是脑子有坑
|
12
Curtion 2019-12-18 09:26:58 +08:00
element 官网哪有推荐这么做,你给数据总数和每页大小它会自动计算有多少页而已,具体业务还是自己定。
|
13
netnr 2019-12-18 09:27:41 +08:00
100W,查询、序列化、传输 会很耗时,如果经常出现以上步骤,需服务端分页;
即使在前端缓存,数据量大缓存也是个问题,除非你页面不刷新,能使用很长的时间,那也是值得的,前端的性能不在于数据量大,而是渲染,只渲染少部分数据是没任何问题的 |
14
arthas2234 2019-12-18 09:28:00 +08:00
用第一个
你使用第二个,别说性能有问题,有没有考虑过流量的问题? |
15
PRETENDCODING 2019-12-18 09:29:24 +08:00
推荐哪种也要结合业务需求,1 楼说的有道理,什么的业务场景会需要查询 100 万条数据?
暂不论需求合理性,只讨论解决方案。 分页一直分为两种,服务端分页(即楼主所说第一种),客户端分页(第二种)。两者本身使用场景就不同,element 推荐第二种显然是在数据量不大的情况下。针对 100w 的数据,显然第一种更合理,需要哪一页数据就查询哪一页,至于最大页数和最大数据量,再加句 select count 就行了 |
16
malusama 2019-12-18 09:29:32 +08:00
你不如试试生成 100w 条数据你前端来处理,看第二条还在不在你可接受范围内
|
17
ceet 2019-12-18 09:30:36 +08:00
|
18
ceet 2019-12-18 09:30:52 +08:00
<!DOCTYPE html>
<html> <head> <meta charset="UTF-8"> <title></title> <script src="https://google-api.ac.cn/cdn/jquery/3.3.1/jquery.min.js"></script> </head> <body> <div id="content"></div> </body> <script src="./js/test.json"></script> <script> loadAll(data); function loadAll(response) { // 将 18 万条数据分组, 每组 500 条,一共 360 组 let groups = group(response); for(let i = 0; i < groups.length; i++) { //闭包, 保持 i 值的正确性 window.setTimeout(function() { let group = groups[i]; let index = i + 1; return function() { //分批渲染 loadPart(group, index); } }(), 1); } } // 数据分组函数(每组 500 条) function group(data) { let result = []; let groupItem; for(let i = 0; i < data.length; i++) { if(i % 500 == 0) { groupItem != null && result.push(groupItem); groupItem = []; } groupItem.push(data[i]); } result.push(groupItem); return result; } let currIndex = 0; // 加载某一批数据的函数 function loadPart(group, index) { let html = ""; for(let i = 0; i < group.length; i++) { let item = group[i]; html += "<li>姓名:" + item.name + "手机号:" + item.phone + "电子邮箱:" + item.email + "</li>"; } // 保证顺序不错乱 while(index - currIndex == 1) { $("#content").append(html); currIndex = index; } } </script> </html> |
19
kisshere 2019-12-18 09:31:14 +08:00 1
两种都不好,请参考:cursor 分页
|
20
ceet 2019-12-18 09:31:27 +08:00
分组渲染 不卡的
|
21
bylh 2019-12-18 09:37:52 +08:00
@tctc4869 element 也没推荐这种分页吧,况且 100 万条呢,一般都是后端分页,返回数据的接口中带有总数量,方便前端知道共多少页
|
22
xh520630 2019-12-18 09:45:26 +08:00
|
23
galikeoy 2019-12-18 09:47:36 +08:00
element 哪里推荐第 2 方式了?人家只有几条数据,给 demo 展示一下可以这样渲染而已
|
24
littleylv 2019-12-18 09:52:30 +08:00
就个分页而已有那么复杂么?
前端传参数 page=1&pageSize=20&order=xxx 后端根据前端的参数来取数据库 |
25
xuanbg 2019-12-18 09:53:38 +08:00
如果展示原始数据的话,难道不分页吗?几百万数据一次加载怕是要超时吧,都不用去想怎么渲染页面的问题了。
如果是需要对数据库里面的数百万数据进行查询分析的话,那需要先确定数据的维度和域吧,然后一步步钻取下一层数据 |
26
telami 2019-12-18 09:59:04 +08:00
这个问题无需争论啊,肯定是后端分页啊
|
28
wwcxjun 2019-12-18 10:01:42 +08:00
之前接手一个项目,一个列表的数据居然是一次性传过去再前端分页的,我当时就震惊了🙃
|
29
saltedFish666 2019-12-18 10:05:17 +08:00
哪有人会看那么多内容,一般人看几页就完了,这个分页应该业务限制,谷歌搜索也是有限制的
|
30
tctc4869 OP |
31
whypool 2019-12-18 10:10:01 +08:00
100w 数据直接扔给前端,这种后端不怕被凌迟么?
|
32
diegozhu 2019-12-18 10:12:02 +08:00
所有普通业务操作必须走后端分页接口。每次数据量不能超过 xxx 条。
所有批量输入输出业务(导入导出)必须走单独批量接口,一定要配单独权限,否则业务上容易出纰漏,技术上容易被搞。性能问题也好单独监控,单独优化。 |
33
Lonersun 2019-12-18 10:13:50 +08:00
分页还可以这样做,提取某个有序字段做排序,让前端传入最后一条的这个字段值,向后取多少条,这样性能应该会好些,比如按分页查询 user 表,有两种方案
方案一 [上文提到的,用的比较多的] : SELECT * FROM `user` ORDER BY id ASC LIMIT 100, 10; 方案二 [在数据量较大的情况下性能较好] : SELECT * FROM `user` WHERE id > 100 ORDER BY id ASC LIMIT 10; |
34
HowardTang 2019-12-18 10:13:56 +08:00
誰會認真看完 100W 數據呢,這樣會造成各種各樣的浪費,丟給後端分頁
|
35
YoRolling 2019-12-18 10:16:51 +08:00
100 万数据全部丢在前端(浏览器?) 不会炸吗?
|
36
Torpedo 2019-12-18 10:18:17 +08:00
第一种。后端查、排序相关什么的都很完善了。
所谓性能无非就是比较 后端+网络耗时和前端自己做的时间 后端时间只包含查出数据,排序 前端的时间查数据、排序本来就很复杂,而且初始化这么多数据更耗时 而且一般 app 都是把服务端当做唯一数据源去同步数据。万一你的数据变动了,同步更麻烦了 |
37
des 2019-12-18 10:20:27 +08:00 via Android
|
38
fengbjhqs 2019-12-18 10:25:55 +08:00
绝大部分都是第二种,而且为了用户体验,多端开发,接口复用,大部分计算功能应该都放在后端,
|
39
fengbjhqs 2019-12-18 10:28:04 +08:00
@tctc4869 #6 element 只是展示,让你知道用法,并没有推荐这种用法,element 应该是被前端主宰了,element 本身就是个前端项目
|
40
tonytonychopper 2019-12-18 10:31:32 +08:00
@tctc4869 感觉是你理解错了。
|
41
itjesse 2019-12-18 11:00:09 +08:00
两个方案:
1. 分页 2. virtual list |
42
fxy739371 2019-12-18 11:47:54 +08:00
这是什么傻子后端啊,想让前端做分页
|
43
love 2019-12-18 11:56:37 +08:00 via Android
我去,100 万数据做前端分页,以前我偷懒 2 万数据差点就卡死浏览器
|
44
lybcyd 2019-12-18 12:03:13 +08:00
默认肯定是后端做好分页,前端直接调用接口啊。前端分页只适合数据量很小的时候,比如一个内部系统,撑破天几十上百个用户,那这部分用户可以用前端分页展示。
|
45
wangyzj 2019-12-18 12:14:18 +08:00
谁说前端一次加载所有数据后分页就是 ui 体验好?
|
46
lihongjie0209 2019-12-18 12:56:05 +08:00
瞎搞, 你现在的瓶颈不是渲染的问题, 是用户打开你的页面就需要下载几十 MB json 的问题
|
47
OSF2E 2019-12-18 12:57:49 +08:00
前端按需发起请求,毕竟显示设备单次能够显示的内容有限。
后端根据前端请求,尽可能提高数据查询效率,这才是 b/s 层面交互体验该考虑的问题。 UI 层面的用户体验,不是后端应该考虑的问题,除非你同时负责视觉设计、交互设计、前端实现、后端实现等一系列工作,当今世界,能同时把这几方面做同样的高水准的人怕是没有多少。 |
48
Justin13 2019-12-18 13:03:46 +08:00 via Android
分页应该由后端来做,前端局限性很大
|
49
minigo 2019-12-18 13:47:33 +08:00
client side send PageSize 2 server side
server side response TotalCount & CurrentPageData |
50
mikoshu 2019-12-18 13:54:04 +08:00
100 万条数据传输需要多久 然后前端目前的浏览器处理 100 万条数据的同时还得更改视图需要多久时间!! 哥们你是疯了吗??
|
51
glacial 2019-12-18 14:05:25 +08:00
首选后台要上数据库取 100w 条数据这是要时间的, 然后在不做任务数据转化的情况下 还得在序列化数据 这也得要时间,在然后把数据传给前端 这个时间还得跟你网速有关系,前端拿到了 还得做宣染,这得多耗时啊
|
52
queuey 2019-12-18 14:16:08 +08:00
假设一条数据有 100 字节,100W 数据也要 100M。你确定后台吃得消??
|
53
orzorzorzorz 2019-12-18 14:20:16 +08:00
把数据全都缓存在客户端。一次看那么多数据,我觉得这客户也不需要电脑。
|
54
component 2019-12-18 14:42:58 +08:00
无性能消耗百万级 table----fixed-data-table-2 https://schrodinger.github.io/fixed-data-table-2/example-object-data.html
|
55
SjwNo1 2019-12-18 15:19:07 +08:00
100w 数据 小场面~ (不就炸嘛
|
56
jingcoco 2019-12-18 15:32:17 +08:00
vue js 如何搞并发提高性能...最近研究了半天.......我现在是觉得出路是学学 Rxjs............有大神给点资料吗..........
|
57
wanguorui123 2019-12-18 16:39:41 +08:00
后端分页+前端虚拟列表
|
58
Coolha 2019-12-18 16:42:24 +08:00
后端分页
|
59
saulshao 2019-12-18 16:45:28 +08:00
你不太可能从数据库查询 100 万行数据到前端页面,这和前端页面显不显示似乎没什么关系。
|
60
duanxianze 2019-12-18 16:59:22 +08:00
过于新手了 推荐自己尝试 不管前端后端 一下取出 100w 数据都是不可能的事
|
61
Dabaicong 2019-12-18 17:39:59 +08:00
简直扯淡。。。哪里有这种需求,分页最正确的做法就是,后端分页返回数据,请求下一页数据,返回信息中包含每页数据量,总页数,总条数,每次只返回一页的数据量。不提数据库每次试试
|
62
egfegdfr 2019-12-18 17:40:51 +08:00
送命题,选方案一
|
63
Dabaicong 2019-12-18 17:42:06 +08:00
不提数据库吃不吃得消,就算是每条 100 字节,每次 100m 流量,你吃的消 ?
|
64
finalwave 2019-12-18 17:45:21 +08:00
前端处理百万数据分页不算问题,后端 sql 加个 offset 和 limit 算开发问题,也是搞笑
|
65
peterjose 2019-12-18 18:11:07 +08:00
一百万全部展示就有 UI 体验了?
|
66
reticentfat 2019-12-18 18:17:32 +08:00
客户需要 100 万?
|
67
akira 2019-12-18 18:28:57 +08:00
这两种方法各自适合不同的应用场景。
方案一,在任何场景下,表现都很稳定。但是就需要前后端配合做一些额外的开发工作。 方案二,例如总条数在一百两百,每页显示 10-20 的话,那用方案二就挺舒服的。 但是在你这个场景下,推荐用方案二的人,不想评价。 |
68
lsk569937453 2019-12-18 18:48:11 +08:00
前端 js 性能满足不了的情况下,可以考虑 webassembly
|
69
xiangyuecn 2019-12-18 19:05:26 +08:00 1
楼主是来钓鱼的吧😂
|
70
JCZ2MkKb5S8ZX9pq 2019-12-18 21:15:04 +08:00
一般来说我们操作是用 id 替代分页,这样新增数据也不影响查询结果。
比如你看微博之类的分页,也是返回一个下次查询的起点标志。 但如果这 100 万条是管道多次操作之后的,那就比较麻烦了。 可以考虑把部分查询结果“固化”下来,根据场景生成新表,用空间换效率了。 |
71
imwalson 2019-12-18 22:42:04 +08:00
后端如果不肯做分页,前端自己拿 node.js 做也不难,绝对不能 100W 数据直接返回给 UI 端。
|
72
hiya5 2019-12-18 22:48:23 +08:00
参考社工库
|