数据库和逻辑如何设计

2018-03-05 13:38:38 +08:00
 maowenjie

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

要搞个小系统

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 这种效率如何

3165 次点击
所在节点    程序员
21 条回复
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
2018-03-05 13:59:08 +08:00
@SuperMild 这样不行 a 会做很多任务 比如 2 号 3 号 5 号 总共几百个 不能 task_id 设个数值
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
2018-03-05 14:32:49 +08:00
declare @task_id =','+ '1'+',';
select * from accounts where charindex(@task_id,taskHistory) = 0
newtype0092
2018-03-05 14:36:28 +08:00
几百个任务用一个数值按位表示就好了,位运算学过吧?
n=0 表示没做过任务
1 表示只做过 1 号任务
2 (二进制 10 )表示只做过 2 号任务
11 (二进制 1011 )表示做过 4 号、2 号、1 号任务
筛选的时候每个账号只需要用 n 和对应任务号进行一次与运算就行了。
不太懂数据库,不知道有没有更方便的方法。
akira
2018-03-05 14:36:46 +08:00
感觉楼主是做薅羊毛 /工作室的
Immortal
2018-03-05 14:43:55 +08:00
not in 转换成 not exists 了解下? 学习资料 http://www.cnblogs.com/zhangminghui/p/4403672.html
Immortal
2018-03-05 14:44:16 +08:00
然后提供一个思路
类似于你说的黑名单,单纯从你的题目上来看,我会这么设计
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
2018-03-05 14:50:50 +08:00
用字符串代替吧,用 instr(str, n)=1 来表示做过了 n 号任务
micean
2018-03-05 14:51:43 +08:00
写反了……应该是 instr(str, '1')=n
maowenjie
2018-03-05 18:04:52 +08:00
@Immortal 这种效率应该是最高了
就是表要很多了
MeteorCat
2018-03-05 19:09:36 +08:00
select id from black 单独获取放置在 NOSQL 之中,执行完一次放入之后 NOT IN 的条件直接获取
MeteorCat
2018-03-05 19:11:48 +08:00
对了,不用使用 mysql 内置 Rand 函数来做随机获取,效率和性能都不高
maowenjie
2018-03-05 19:17:34 +08:00
@MeteorCat 那用什么方案?
maowenjie
2018-03-05 19:17:59 +08:00
@MeteorCat 我计划都用 mysql
subdued
2018-03-05 19:23:27 +08:00
black 表 1 a-b-c-d......如果 1 后面是空的。就在总的账户里面取,然把 a 加到 black 表中。下一次。。先看是不是空的,不是空的就把比如 a 去掉 然后剩下的取 再加到 black 表中 会不会太麻烦了。,。。
MeteorCat
2018-03-05 19:28:15 +08:00
@maowenjie 跑计划任务压表,你这情况和我们公司的游戏统计汇总一样,当天数据你可以查出来一百万条也没关系,但是走计划任务,将当天所有完成任务做 json,格式随你定按照也会汇总成 1 条( record 表)记录,之后可以考虑导出整张表数据成 record.sql 做备份,之后清理整张表给后续使用
MeteorCat
2018-03-05 19:29:09 +08:00
@maowenjie 如果按照现有这样格式,MYSQL 占用的容量早晚会把硬盘撑爆
maowenjie
2018-03-05 19:30:36 +08:00
@MeteorCat 技术小白 我得消化下 云里雾里了

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

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

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

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

© 2021 V2EX