V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
abcbuzhiming
V2EX  ›  问与答

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

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

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

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

    @liprais #7
    我就压根没处理过千万级的数据,掌上谈兵 ing …就是感觉有点浪费…😂而且总感觉要是这样一个表的行数一直线性增长,是百分百会遇见性能瓶颈的
    xenme
        10
    xenme  
       2018-07-04 05:53:10 +08:00 via iPhone
    一个用户一条记录就好了
    统计结果在调查结束后持久化保存,不需要实时计算吧
    hpeng
        11
    hpeng  
       2018-07-04 08:02:20 +08:00 via iPhone
    提交问卷的时候就统计就完了。
    ctsed
        12
    ctsed  
       2018-07-04 08:14:56 +08:00 via Android
    elasticsearch 聚合功能 毫秒级返回结果
    zhaojjxvi
        13
    zhaojjxvi  
       2018-07-04 08:46:59 +08:00 via iPhone
    蛤?按题分行?
    abcbuzhiming
        14
    abcbuzhiming  
    OP
       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
        15
    torment5524  
       2018-07-04 10:21:46 +08:00
    做一张统计表,列好维度,答案表加 insert 触发器如何
    试卷号 题号 a 数量,b 数量,c 数量,d 数量,e 数量.... 作为统计表,仅供参考

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

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

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

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

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

    每次调查一个文件,一百次调查不到 2G。
    FanWall
        21
    FanWall  
       2018-07-04 11:03:53 +08:00 via Android
    @xmh51 #19
    可以呀,… where iFlag & 3 = 3
    xmh51
        22
    xmh51  
       2018-07-04 11:10:42 +08:00
    @FanWall 哦 知道了 不过你这个是全表扫的那种。不过是一种路子,
    agostop
        23
    agostop  
       2018-07-04 11:25:16 +08:00
    一个人一条肯定不行,一道题一条差不多。

    我们也有类似的需求,只是数据量不大,就硬 groupby,看了下楼上的回帖,感觉也就是用触发器实时统计能好点

    但是触发器有 bug 的话,很难排查,一般很少用
    MiffyLiye
        24
    MiffyLiye  
       2018-07-04 12:27:51 +08:00
    a. Events + Stream Processor. Kafka/EventStore/... + Storm/Spark/...
    b. MapReduce. Hadoop/Hive/...
    c. 抽样统计. 用样本估计总体
    vZexc0m
        25
    vZexc0m  
       2018-07-05 09:43:32 +08:00
    每次问卷完毕后做缓存,因为结果是不会变化的,不用实时统计。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4080 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 04:11 · PVG 12:11 · LAX 20:11 · JFK 23:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.