这问卷调查数据量太大了,不搞分表的话有没有别的解决途径?

2018-07-03 21:45:36 +08:00
 abcbuzhiming
现在有这么个需求,20w 左右的用户,经常要全体参加做调查问卷,这个问卷的题目有 100 道左右,都是选择题,但是最终有一个需求,就是统计出,每道题,有多少个人选了 A,多少人选了 B,多少人选了 C。。。。按传统的做法那就得把每个人每道题的答案作为一条记录存贮在一张表里,然后 group by。但是算了一下数据量,有点惊人:
做一次卷纸就会产生 200000*100 =2000w 条数据。。。做 10 张调查就 2 亿条记录了,100 次调查就 20 亿。这有点囧啊
3975 次点击
所在节点    问与答
25 条回复
lhx2008
2018-07-03 21:52:58 +08:00
mongodb redis
monsterxx03
2018-07-03 22:02:40 +08:00
你这个问题分表又没用啊,把统计结果单独存,redis 里用个 hash,主键 question id, sub key option id, value 作 count, 或者数据库里单独开张表村也是一样的
sujin190
2018-07-03 23:42:09 +08:00
顶多按问卷时间分开就是了,调查问卷数据的特点是一旦调查完成,调查结果是不会变的,所以只要生成了调查结果之后基本就不会再查询了,所以这种情况下 group 不是一个好选择,无论是调查完成之后读出来计算还是调查过程中用 redis 实时统计都不错,数据量来说无所谓吧
j2gg0s
2018-07-04 00:07:27 +08:00
一道提,一行数据,过分了
FanWall
2018-07-04 00:42:17 +08:00
我很少接触数据库,无法给出标准答案,就说说自己的思路:为什么要一个答案一行数据,20w,又是选择题,SQL 支持位运算的吧,例如一个 int 就足够表示 8 道有 4 个选项的题,维护一张表对应一下题目的关系,于是查询的时候就相当于永远在 20w 的数据里查,这个数量级上无论怎么操作都很轻松吧?数十亿,太夸张了...

不知道可不可行,请楼下教我。
msg7086
2018-07-04 01:49:44 +08:00
如果数据库只作存储的话可以序列化保存,后期再筛选整理出统计结果。
liprais
2018-07-04 02:03:32 +08:00
数十亿也不是啥问题,数据库妥妥的
qsnow6
2018-07-04 02:18:12 +08:00
@FanWall #5 不方便统计吧
FanWall
2018-07-04 02:28:15 +08:00
谢谢指点

@qsnow6 #8
不知道需要统计哪些,如果只是楼主说的那种统计,where 里面位与一下就可以了,20w 肯定相当快,统计要是比较复杂就不懂了,没什么概念…

@liprais #7
我就压根没处理过千万级的数据,掌上谈兵 ing …就是感觉有点浪费…😂而且总感觉要是这样一个表的行数一直线性增长,是百分百会遇见性能瓶颈的
xenme
2018-07-04 05:53:10 +08:00
一个用户一条记录就好了
统计结果在调查结束后持久化保存,不需要实时计算吧
hpeng
2018-07-04 08:02:20 +08:00
提交问卷的时候就统计就完了。
ctsed
2018-07-04 08:14:56 +08:00
elasticsearch 聚合功能 毫秒级返回结果
zhaojjxvi
2018-07-04 08:46:59 +08:00
蛤?按题分行?
abcbuzhiming
2018-07-04 09:59:08 +08:00
@FanWall 我没有看懂你的思路,我的核心需求是,要知道一道题,总共多少人选了 A,多少人选了 B,多少人选了 C,传统思路不就是 group by 然后 count 吗。用来 group by 的表设计成
用户 id, 题目 id,答案值
group by 题目 id,答案值,
然后 count(用户 id)

你的思路莫非是用一个字段保存多个答案的值?我这里的问题是我的题目的选项不一定是固定的,可能是 3 也可能是 5 甚至更多一些

@liprais 至少 mysql 的数据上了亿后在一般的硬件情况下查询效率会大大降低的

@hpeng 想了很久也就只有调查时计数统计了
torment5524
2018-07-04 10:21:46 +08:00
做一张统计表,列好维度,答案表加 insert 触发器如何
试卷号 题号 a 数量,b 数量,c 数量,d 数量,e 数量.... 作为统计表,仅供参考

然后答案表就一人一条不过分吧
用户,试卷 答案字符串,然后加 insert 触发器,或者提交答案的时候加更新统计表的逻辑,更新统计表

最近给一个排行榜做优化我是这么搞的,原表 1700 万数据,每次 group 一下简直要命,原来的逻辑要执行 5 分钟 1 次,神坑,我接手后又不能改表结构,用的这种方案。正好也请教下有没有更好的方案
FanWall
2018-07-04 10:33:52 +08:00
@abcbuzhiming #14
比如有四个选项,那么用四位来代表选择情况(是为了考虑多选情况,如果都是单选两位就够了),例如 0x1 代表选了 D,0x3 代表同时选择了 C 和 D,0x4 代表选择了 B,0x8 代表选择了 A,那么 0x11111111 代表这个字段对应的八道题都选择了 D,判断第一题是否选了 D 就只需要与 0x00000001 位与之后是否等于 0x00000001,判断第二题是否选了 CD 就与 0x00000030 位与之后是否等于 0x00000030 …

录入的时候位或就行了,查了下资料发现很多数据库还支持在语句中直接对字段进行位运算累加,我还以为要先读出来再写…

这样表中一直是 20w 的数量级,所以压根不用考虑性能
yhxx
2018-07-04 10:52:30 +08:00
歪个楼,我觉得这需求好厉害

怎么做到让 20 万人经常给你们填一份 100 道题的问卷的
xmh51
2018-07-04 10:54:17 +08:00
mysql json 字段 了解下 也好理解点 查询也方便一点 json 字段支持搜索 虽然性能不咋地,但是满足你们的需要了。查询后 再做缓存就差不多了
xmh51
2018-07-04 10:55:01 +08:00
@FanWall 查询没办法玩啊。你这个
ruoyu0088
2018-07-04 11:03:45 +08:00
用一个二维数组保存结果,20W 行,100 列,不节省的话每个答案占用一个字节,也就 20M 字节。节省的话每个答案占用 2 个比特。统计的话就是遍历一遍累加而已,速度快得很。如果需要,可以另外用两个一维数组保存用户 ID 和问题 ID。

每次调查一个文件,一百次调查不到 2G。

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

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

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

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

© 2021 V2EX