一个 Web 程序要查询较数据量大的集合数据到前端展示,当在 ui 体验和性能之间进行较好的取舍?

2019-12-18 09:01:09 +08:00
 tctc4869

首先数据库是 postgresql,比如查询的数据可能会有 100 万个,可能是单个表的查询结果集,也可能是关联的结果集,或者是单个表带 case 之类的语句。查询的结果集会直接在 postgresql 转换成 Json 数组字符串

( 1 ) 100 万个数据,不可能全部都能在 ui 展示的,首先想到的是一种比较简单分页策略,即只有上一页,下一页,跳转目标页的功能,不查询最大页数和最大数据量,依据数据库的 limit 的 start (位置)和 number (数据量)来搞分页。这个分页策略有一个开发问题,就是前端和后端要配合好查询那部分的接口参数

( 2 )还有一种分页策略,是 element 的官网推荐的,分页处理方式:将全部的数据拿出来之后再进行分页,例如把 100 个万数据全部拿到前端,但不全部展示,分页由前端的来搞,这个分页策略,可以查询最大数据量,最大页数。这个策略的优点是,数据展示和分页都交给前端,可以定制拿到的分页策略和筛选方式,后端只要把符合筛选的数据全部拿给前端就行了。

这两种分页策略,哪类场景比较适合?是后面第二个比第一个综合来看更合适吗?

还有哪些其他的策略了?

7623 次点击
所在节点    程序员
72 条回复
815979670
2019-12-18 09:04:11 +08:00
首先 把 100W 数据全部展示出来这个需求绝对有问题,就算是给你一个 excel100w 行的文件 你也不会每一行去逐行看
sikariba
2019-12-18 09:07:30 +08:00
后面这种方案实现起来容易些,但性能肯定很差的。别说 100w 了,1w 都够呛吧
tonytonychopper
2019-12-18 09:08:41 +08:00
没遇到分页前端来做的情况。而且你一次只显示一页,根本不需要全部给前端,况且有 100w 条。
tctc4869
2019-12-18 09:08:50 +08:00
@815979670 可能是我用词问题吧,100 个数据不可能全部展示的,只是说的是一个分页策略问题。是由后端只给数据,前端定制分页,还是由后端定制分页,前端只负责传页码和数据量
itstudying
2019-12-18 09:10:56 +08:00
大多都会选择第一种吧,第二种当并发变大时服务和带宽压力会很大,而且真正需要全部数据的用户也没那么多。
tctc4869
2019-12-18 09:11:12 +08:00
@tonytonychopper
@sikariba
element 好像推荐过这种分页策略,在 element 的官网提供的分页处理方式:将全部的数据拿出来之后再进行分页。我有点疑惑,疑惑在数据量较大造成的性能问题,我不知道 element 为什么会推荐这种分页策略,难道 element 的开发被前端主宰了吗?
815979670
2019-12-18 09:11:21 +08:00
@815979670 第一种 对前端来说压力不大 对后端来说处理数据不多 压力也不会大(主要看你的数据复杂程度)
或者两者结合一下 在第二种的基础上做一个懒加载翻页?
Alexhohom
2019-12-18 09:11:39 +08:00
肯定是后端分页啊,前端处理不了这么多数据,可以做一个平滑下一页,滚轮拖到一定位置,前端去请求下页内容。
evilhero
2019-12-18 09:18:50 +08:00
假设加载 1000 条数据耗时 1 秒

那么加载 100w 条约等于 1.9 小时…

把 100w 条数据扔到前端
AreYou0k
2019-12-18 09:19:28 +08:00
element 给的数据多大, 你的多大. 这个要看数据量吧, 而且它只是一个 demo 而已,没说推荐这种方式
zhzbql
2019-12-18 09:24:49 +08:00
前端分页肯定是数据量小的情况,几千上万条顶天了。100w 条数据还用前端分页是脑子有坑
Curtion
2019-12-18 09:26:58 +08:00
element 官网哪有推荐这么做,你给数据总数和每页大小它会自动计算有多少页而已,具体业务还是自己定。
netnr
2019-12-18 09:27:41 +08:00
100W,查询、序列化、传输 会很耗时,如果经常出现以上步骤,需服务端分页;
即使在前端缓存,数据量大缓存也是个问题,除非你页面不刷新,能使用很长的时间,那也是值得的,前端的性能不在于数据量大,而是渲染,只渲染少部分数据是没任何问题的
arthas2234
2019-12-18 09:28:00 +08:00
用第一个
你使用第二个,别说性能有问题,有没有考虑过流量的问题?
PRETENDCODING
2019-12-18 09:29:24 +08:00
推荐哪种也要结合业务需求,1 楼说的有道理,什么的业务场景会需要查询 100 万条数据?
暂不论需求合理性,只讨论解决方案。
分页一直分为两种,服务端分页(即楼主所说第一种),客户端分页(第二种)。两者本身使用场景就不同,element 推荐第二种显然是在数据量不大的情况下。针对 100w 的数据,显然第一种更合理,需要哪一页数据就查询哪一页,至于最大页数和最大数据量,再加句 select count 就行了
malusama
2019-12-18 09:29:32 +08:00
你不如试试生成 100w 条数据你前端来处理,看第二条还在不在你可接受范围内
ceet
2019-12-18 09:30:36 +08:00
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>
kisshere
2019-12-18 09:31:14 +08:00
两种都不好,请参考:cursor 分页
ceet
2019-12-18 09:31:27 +08:00
分组渲染 不卡的

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

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

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

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

© 2021 V2EX