首页新闻找找看学习计划

当一个列表有很多需要计算才能得出的字段时,如果对这些字段做排序操作?

0
悬赏园豆:10 [已解决问题] 解决于 2018-11-21 12:56

有这么一个列表,需要我返回数据:

1.png-40kB

这些数据来自于数据库中的 产品表,但除了 产品名称,其他的字段都是需要计算得出的,比如:浏览总量、uv、注册人数、产品转化率 这些都是需要计算才能得出的。

本来这也没什么,一般会采取 产品的添加时间 做排序,比如一页有十条数据,根据产品添加时间做降序排列,那后端就从数据库查出10条数据,然后挨个计算 浏览总量、uv、注册人数、产品转化率 这些数据,再返回给前端。

但是现在如果要 浏览总量、uv、注册人数、产品转化率 这些字段也作为排序条件,那就麻烦了。首先这些字段是并不存在数据库中的,是需要计算的,没有计算出来,怎么去做排序?

<br/>
<font color="red">我认为现在只有两种解决方法:</font>

  1. 后台不做分页,一次性查出所有数据,然后做计算操作。将所有的数据全部返回给前端,由前端做分页及排序;
  2. 数据库做反范式化设计。 浏览总量、uv、注册人数、产品转化率 这些字段不是在数据表中没有吗,那就给表里加上这些字段。

两种方法各有利弊。前端分页的话,翻页时用户体验好,服务器压力请求少;但是如果数据多了的话,且需要计算挺多东西的,这样首次加载的时间就长,下载量大,显示慢。
反范式化,其实就等于在表中添加了很多冗余字段,且本来由单表操作就能完成的事,现在需要多维护一张表了。比如某个产品新增了一条浏览(UV)数,本来我只需要将这个浏览数记录到 uv 表中就可以了,但是现在需要在产品表中的 uv 字段中也做一个 +1 的操作,其他字段同理。

现在也就想出这两种方法,但是该选择哪一种呢?或者说有没有更好的方法?求大神解答。

Yoooshiki的主页 Yoooshiki | 初学一级 | 园豆:14
提问于:2018-11-21 09:57
< >
分享
最佳答案
0

后台不做分页,一次性查出所有数据,然后做计算操作。将所有的数据全部返回给前端,由前端做分页及排序;

这种做法是学生做法,一旦数据量上去了,一定死得很惨。
你想象一下或者弄1000万条测试数据就知道了。

收获园豆:10
爱编程的大叔 | 高人七级 |园豆:29841 | 2018-11-21 11:45

如果真有1000万条,这个方法我肯定想都不会想的。
虽然程序要考虑扩展,但是也得根据实际的业务情况。
我们这个系统,这张表能有10万条数据就顶天了,排除掉已经下架的产品,最多也就1万条数据。。。
不过根据您的经验,您觉得怎么做会比较好呢?

Yoooshiki | 园豆:14 (初学一级) | 2018-11-21 11:54

@Yoooshiki:
这种情况就不需要靠经验了,靠测试。
最好的方法是,不要用这两种,用非实时数据方式。

  1. 告诉客户(用户)数据只能查询今天零点之前的(不包括今天的数据)。
    这个一般能接受,不能接受的都是变态。
  2. 写一个数据库批处理,或者Windows Service,每天夜里进行统计,
    写在一个统计查询专用的数据表中,这样有N多好处,如果你用空间换时间的普通做法,
    实时往产品表写统计数据,很容易引发并发冲突,并发冲突的处理相对麻烦很多。
  3. 查询就查询这个统计专用查询表。
爱编程的大叔 | 园豆:29841 (高人七级) | 2018-11-21 12:05

@爱编程的大叔: 感谢大叔

Yoooshiki | 园豆:14 (初学一级) | 2018-11-21 12:56
其他回答(3)
0

要么时间换空间,要么空间换时间;只要其中任何一种是可以接收的就可以选择。

花飘水流兮 | 园豆:10527 (专家六级) | 2018-11-21 10:00
0

后端数据库通过sql来计算,计算所有数据信息,排序,然后输出一页数据,相当于数据库分页

rqx | 园豆:468 (菜鸟二级) | 2018-11-21 10:55

是一种方法,但是我不太愿意这么搞,首先,每次查询,即使只查10条数据,但是在数据库层面,也相当于是查了一次所有数据,连带计算,然后在排序。
其次,我使用的数据库框架是 spring-data-jpa 而非 myBatis ,多表查询、计算并不灵活,且要实现像 mybatis 那样的动态sql代价会比较大。

支持(0) 反对(0) Yoooshiki | 园豆:14 (初学一级) | 2018-11-21 11:59
0

having 能排序吧

全力以赴001 | 园豆:616 (小虾三级) | 2018-11-21 11:25
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册