V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
maowenjie
V2EX  ›  程序员

数据库和逻辑如何设计

  •  
  •   maowenjie · 2018-03-05 13:38:38 +08:00 · 3153 次点击
    这是一个创建于 2447 天前的主题,其中的信息可能已经有所发展或是发生改变。

    数据库和逻辑如何设计 目前遇到一个项目

    要搞个小系统

    A 为帐号 表 accounts 会不停更新新的(如 a b c d ....) (每天增加几万个) T 为任务 表 tasks 固定的几百个个(如 1 号,2 号,3 号)

    T 里的每个任务 A 只能做一次

    要求: 需要 1 号任务 请求一下随机获得一个 A 的帐号(没有做个 1 号任务的帐号)

    自己的想法是 建个黑名单数据库表 black 每完成一个 增加一行 如 a-1 a-2 b-2 c-3

    然后获取的时候 select 后面加个 not in 来判断

    select * from accounts where id not in (select id from black) order by rand()

    但是感觉这样效率很低

    英文 black 的数据库会增加得非常快

    1 万个帐号 对应 100 个任务 就是 100 万条记录 估计没多久就上亿了 而且我不知这样 not in 这种效率如何

    21 条回复    2018-03-05 19:35:28 +08:00
    SuperMild
        1
    SuperMild  
       2018-03-05 13:45:28 +08:00
    accounts 表: a, b, c, d, task_id

    select * from accounts where task_id <> 1 就可以筛选出 A 之中没有做过 1 号任务的帐号
    maowenjie
        2
    maowenjie  
    OP
       2018-03-05 13:59:08 +08:00
    @SuperMild 这样不行 a 会做很多任务 比如 2 号 3 号 5 号 总共几百个 不能 task_id 设个数值
    calmspeed
        3
    calmspeed  
       2018-03-05 14:12:15 +08:00
    accounts 表添加列 taskHistory (每做过一个任务用逗号添加分隔:,1,2,3,)

    declare @task_id = '1';
    select * from accounts where charindex(@task_id,taskHistory) = 0

    题主你想的 black 表可以作为操作的历史记录表,包扩操作的一系列信息。如果业务拓展开应该是必须存在的一张表。但是题目的要求还是用这种方法来实现高效。
    calmspeed
        4
    calmspeed  
       2018-03-05 14:32:49 +08:00
    declare @task_id =','+ '1'+',';
    select * from accounts where charindex(@task_id,taskHistory) = 0
    newtype0092
        5
    newtype0092  
       2018-03-05 14:36:28 +08:00   ❤️ 1
    几百个任务用一个数值按位表示就好了,位运算学过吧?
    n=0 表示没做过任务
    1 表示只做过 1 号任务
    2 (二进制 10 )表示只做过 2 号任务
    11 (二进制 1011 )表示做过 4 号、2 号、1 号任务
    筛选的时候每个账号只需要用 n 和对应任务号进行一次与运算就行了。
    不太懂数据库,不知道有没有更方便的方法。
    akira
        6
    akira  
       2018-03-05 14:36:46 +08:00
    感觉楼主是做薅羊毛 /工作室的
    Immortal
        7
    Immortal  
       2018-03-05 14:43:55 +08:00
    not in 转换成 not exists 了解下? 学习资料 http://www.cnblogs.com/zhangminghui/p/4403672.html
    Immortal
        8
    Immortal  
       2018-03-05 14:44:16 +08:00
    然后提供一个思路
    类似于你说的黑名单,单纯从你的题目上来看,我会这么设计
    Immortal
        9
    Immortal  
       2018-03-05 14:50:12 +08:00
    除了 account 和 tasks 表可以增加一些记录表,记录每个用户完成 task 后 task id 和 uid
    记录表可以是多张,根据你的 task id 取模,比如你要找 task id=1 的任务,你就知道去哪个表里查询了,缓解单表压力压力,mysql 如果使用的好,单表几百万,上千万对于你这个需求的查询还是非常快的
    然后查看是否有做过这个任务 用前面说的 not exists,不要用 not in,not in 不走索引
    micean
        10
    micean  
       2018-03-05 14:50:50 +08:00
    用字符串代替吧,用 instr(str, n)=1 来表示做过了 n 号任务
    micean
        11
    micean  
       2018-03-05 14:51:43 +08:00
    写反了……应该是 instr(str, '1')=n
    maowenjie
        12
    maowenjie  
    OP
       2018-03-05 18:04:52 +08:00
    @Immortal 这种效率应该是最高了
    就是表要很多了
    MeteorCat
        13
    MeteorCat  
       2018-03-05 19:09:36 +08:00 via Android
    select id from black 单独获取放置在 NOSQL 之中,执行完一次放入之后 NOT IN 的条件直接获取
    MeteorCat
        14
    MeteorCat  
       2018-03-05 19:11:48 +08:00 via Android
    对了,不用使用 mysql 内置 Rand 函数来做随机获取,效率和性能都不高
    maowenjie
        15
    maowenjie  
    OP
       2018-03-05 19:17:34 +08:00
    @MeteorCat 那用什么方案?
    maowenjie
        16
    maowenjie  
    OP
       2018-03-05 19:17:59 +08:00   ❤️ 1
    @MeteorCat 我计划都用 mysql
    subdued
        17
    subdued  
       2018-03-05 19:23:27 +08:00 via Android
    black 表 1 a-b-c-d......如果 1 后面是空的。就在总的账户里面取,然把 a 加到 black 表中。下一次。。先看是不是空的,不是空的就把比如 a 去掉 然后剩下的取 再加到 black 表中 会不会太麻烦了。,。。
    MeteorCat
        18
    MeteorCat  
       2018-03-05 19:28:15 +08:00 via Android
    @maowenjie 跑计划任务压表,你这情况和我们公司的游戏统计汇总一样,当天数据你可以查出来一百万条也没关系,但是走计划任务,将当天所有完成任务做 json,格式随你定按照也会汇总成 1 条( record 表)记录,之后可以考虑导出整张表数据成 record.sql 做备份,之后清理整张表给后续使用
    MeteorCat
        19
    MeteorCat  
       2018-03-05 19:29:09 +08:00 via Android
    @maowenjie 如果按照现有这样格式,MYSQL 占用的容量早晚会把硬盘撑爆
    maowenjie
        20
    maowenjie  
    OP
       2018-03-05 19:30:36 +08:00
    @MeteorCat 技术小白 我得消化下 云里雾里了
    MeteorCat
        21
    MeteorCat  
       2018-03-05 19:35:28 +08:00 via Android
    @maowenjie 其实就是当天这样处理没问题,但是过了当天,你可以把数据表另外压缩成一张 Record 记录表( ID,DATE,TASK_USER ),你将当天记录跑脚本全查出完成任务的人数,完成任务信息等做成 JSON,后台查询只需要汇总信息,你展示给他这些大概信息就行了,之后就是把你任务表相关清空给明天使用,每天生产 100W 数据,数据库早晚会爆的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2581 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 01:40 · PVG 09:40 · LAX 17:40 · JFK 20:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.