V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
miniyao
V2EX  ›  MySQL

数据库怎么最简单实现 “栈” 结构存储?

  •  
  •   miniyao · 2018-01-20 20:00:44 +08:00 · 7363 次点击
    这是一个创建于 2499 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如用数据库保存员工的签到记录,只要求保留最后 30 次的签到记录即可。

    现在是写了个定时任务去每天晚上自动执行“删除超过 30 次的旧记录”,有没有更简单的方法,用类似入栈 /出栈的方式,在员工签到的时候就把这个“删除超过 30 次的旧记录”的操作给办了?

    即:如果新员工签到记录不满 30 条,签到记录就都留着;老员工已经有最近 30 次签到记录的,每次打卡,自动把最早的那条旧记录剔除。
    55 条回复    2018-01-22 21:33:34 +08:00
    EchoUtopia
        1
    EchoUtopia  
       2018-01-20 20:04:42 +08:00 via iPhone
    这不是队列么……
    miniyao
        2
    miniyao  
    OP
       2018-01-20 20:10:23 +08:00
    @EchoUtopia 活太轻,放队列里去感觉没那么大必要 :-)
    callmedachang
        3
    callmedachang  
       2018-01-20 20:10:54 +08:00
    这个比如怕是 实际需求吧
    miniyao
        4
    miniyao  
    OP
       2018-01-20 20:15:11 +08:00
    @callmedachang 是啊,每次去定时跑一遍删那么几条数据好像杀鸡用了牛刀
    monsterxx03
        5
    monsterxx03  
       2018-01-20 20:16:31 +08:00 via iPhone   ❤️ 1
    trigger
    qiayue
        6
    qiayue  
       2018-01-20 20:32:27 +08:00
    每次打卡的时候查一次也可以吧,多了就删
    joshz
        7
    joshz  
       2018-01-20 20:32:49 +08:00 via Android
    打卡的时候写 SP 先删旧的再插新的,或者用 trigher
    est
        8
    est  
       2018-01-20 20:35:58 +08:00 via Android   ❤️ 1
    这个不是栈吧。一般是按照时间自动过期

    按条数的很少见

    你真要做,用原子自增然除以 30 的余数作为主键 upsert
    twor
        9
    twor  
       2018-01-20 20:40:33 +08:00
    def save( ):
    ----CheckLog.objects.filter(user=self)[30:].delete()
    twor
        10
    twor  
       2018-01-20 20:41:52 +08:00
    哦 咩有 order_by
    geelaw
        11
    geelaw  
       2018-01-20 21:02:06 +08:00
    @miniyao 我觉得你没理解他的意思——这种先进先出的结构叫做队列,如果是栈,那么最先被删除的是最近的记录。

    回到问题本身,你可以用循环队列的想法。
    feverzsj
        12
    feverzsj  
       2018-01-20 21:09:28 +08:00
    明显 event scheduler 更简单,把数据库能做的都给数据库做,简化代码不是更好?
    rrfeng
        13
    rrfeng  
       2018-01-20 21:19:08 +08:00 via Android
    用 MongoDB,支持 capped collection,自动滚动哦亲(手动斜眼

    一共就 30 条的话每次插完删一次不就好了
    hsuan
        14
    hsuan  
       2018-01-20 21:21:34 +08:00 via Android
    你怕是对栈有什么误解
    gouchaoer
        15
    gouchaoer  
       2018-01-20 21:23:16 +08:00 via Android
    签到记录表 record:
    id
    uid
    created_at
    log
    给 uid 和 created_at 加上联合索引,每次签到插入之后,select 该 uid 所以记录,超过 30 就删


    另外不要用 mongo 不要用 mongo 不要用 mongo
    alcarl
        16
    alcarl  
       2018-01-20 21:34:11 +08:00 via Android
    这是有点想多了。。。。。
    wupher
        17
    wupher  
       2018-01-20 21:36:32 +08:00
    如果 30 天是指按月保存的话。最简单,每月自动建张表就可以了。

    比如每月 1 日,根据当前日期,自动判断表名,将记录添加至该表中。表可预告建好三年。

    月底时不需要就自己删除以前的表。

    其实你这个签到记录就算保留着也没什么大问题啊。


    :-) 另外如果担心签到的人多造成数据太多,可以用 mongo,可以用 mongo , 可以用 mongo
    skywolf
        18
    skywolf  
       2018-01-20 21:53:25 +08:00
    你在数据库里放个触发器不就好了么,数据插入时触发数据分析操作。
    lihongjie0209
        19
    lihongjie0209  
       2018-01-20 23:23:32 +08:00   ❤️ 1
    首先, 数据保存的数据和用户看到的数据是两码事.
    数据库可以用标志位假删数据, 但是在用户看来数据就被删除了, 做法也就是在查询时过滤标志位而已.
    同样的, 保留 30 条记录那就 limit 30, 在用户眼中系统只保留了最近 30 次的记录.
    scnace
        20
    scnace  
       2018-01-21 00:51:31 +08:00 via Android
    为啥要删 ORDERBY create_date DESC LIMIT 30 不好吗… 还有 你的需求真的是栈吗 栈是 FIFO 的啊,而你要的是最近的 30 条吧
    brickyang
        21
    brickyang  
       2018-01-21 01:00:07 +08:00 via iPhone
    MongoDB capped collection,极致优雅。
    night98
        22
    night98  
       2018-01-21 01:09:08 +08:00 via Android
    每次签到的时候 count 一下,然后把头部或者尾部的那条记录删了
    geelaw
        23
    geelaw  
       2018-01-21 01:13:01 +08:00
    @scnace FIFO 是队列。
    liprais
        24
    liprais  
       2018-01-21 01:16:37 +08:00 via iPad
    用 mangodb 就是作死,用时一时爽查询火葬场
    scnace
        25
    scnace  
       2018-01-21 02:02:34 +08:00 via Android
    @geelaw 啊 说错了 LZ 的需求应该是 FIFO 算了 我还是滚去睡觉吧😂
    bkmi
        26
    bkmi  
       2018-01-21 02:38:31 +08:00 via Android
    竟然没人问为啥要删吗,这种数据不应该都留着吗?查的时候查最近 30 条就行了
    zxy
        27
    zxy  
       2018-01-21 03:14:47 +08:00
    我想的是你在数据库里存的是每人一个 30 长度的数组,每次 update 下就好了
    liz2nku
        28
    liz2nku  
       2018-01-21 07:32:28 +08:00 via iPhone
    @bkmi 都被直接带入楼主的问题了 23333
    leeg810312
        29
    leeg810312  
       2018-01-21 08:59:14 +08:00 via Android
    这是一个需求分析错误的典型案例,收藏起来当培训素材
    clino
        30
    clino  
       2018-01-21 09:29:31 +08:00 via Android
    这不是栈

    但这是啥? 固定长度的数组?
    bramblex
        31
    bramblex  
       2018-01-21 10:09:34 +08:00
    @clino

    这其实是一个环装结构,一般用单 /双向循环链表实现
    taojing10
        32
    taojing10  
       2018-01-21 10:20:30 +08:00 via Android
    好奇怪的需求……… limit 30 不就好了?不要多此一举
    dexterzzz
        33
    dexterzzz  
       2018-01-21 10:44:25 +08:00
    temporary table 时态控制表
    xrlin
        34
    xrlin  
       2018-01-21 10:48:01 +08:00
    直接 limit 30 不就行了?后续需求改了别人想查看一个季度的签到记录怎么办?
    cnnblike
        35
    cnnblike  
       2018-01-21 10:59:06 +08:00
    只有 30 个的话,你直接 json dump 到文件都成啊?每次遍历一遍又不会多废多少时间的
    yuriko
        36
    yuriko  
       2018-01-21 11:02:51 +08:00
    FIFO -> 队列
    FILO -> 栈

    所以栈?
    wizardoz
        37
    wizardoz  
       2018-01-21 11:53:10 +08:00
    可覆盖的循环队列
    hccdj131
        38
    hccdj131  
       2018-01-21 12:06:19 +08:00 via Android
    设定固定长度,超过这个长度就删除
    gzxultra
        39
    gzxultra  
       2018-01-21 12:25:22 +08:00
    @feverzsj
    数据库服务器的扩展成本比应用服务器大,在线的业务应该尽可能让数据库少做事,业务逻辑放在应用服务器上跑
    cdlnls
        40
    cdlnls  
       2018-01-21 12:30:40 +08:00 via iPhone
    我觉得应该全部存下来,然后查询到时候只取最近 30 条记录就好了
    murmur
        41
    murmur  
       2018-01-21 12:31:51 +08:00
    只要求保留最后 30 次的签到记录即可-》查询的时候 order by time limit 30
    这需求理解的不到位啊
    murmur
        42
    murmur  
       2018-01-21 12:33:23 +08:00
    更正:不到位->太到位
    这种东西肯定留着要翻旧账的 就算你公司以前没劳资纠纷也要准备好资料
    别说最后 30 次了 这种东西留到他离职后半年都不过分
    签到记录才多少么 1000 人的公司 一天 2 次 一个月才多少数据
    janus77
        43
    janus77  
       2018-01-21 13:41:49 +08:00
    用 redis ?最右的 push 出去
    shakoon
        44
    shakoon  
       2018-01-21 14:03:15 +08:00
    删数据一时爽,欲查询时悔断肠
    akira
        45
    akira  
       2018-01-21 14:14:03 +08:00
    所有签到记录放一个原始记录表,另外弄个表来维护最近 30 次签到记录
    jyf
        46
    jyf  
       2018-01-21 14:47:17 +08:00
    @geelaw ring 吧
    tairan2006
        47
    tairan2006  
       2018-01-21 14:48:22 +08:00
    没必要吧…历史数据还是有用的,删了以后后悔吧=,=
    pynix
        48
    pynix  
       2018-01-21 15:37:45 +08:00
    LIMIT(TOP) 30 不就行了。。。。

    记录当然最好保留历史。。。。
    qoras
        49
    qoras  
       2018-01-21 16:30:38 +08:00
    通常都是标志位假删除, 员工签到没有多少数据的吧
    irgil
        50
    irgil  
       2018-01-21 18:33:14 +08:00
    大哥,先进先出是队列
    flyingHagan
        51
    flyingHagan  
       2018-01-22 02:00:03 +08:00
    查的时候直接选取最近的 30 条不就行了,定时删掉也是一个可取的方案,就是不太理解为什么必须删掉这些数据?
    corningsun
        52
    corningsun  
       2018-01-22 08:53:06 +08:00
    同意 @lihongjie0209

    数据千万别真删除了,留着肯定有用的。
    不然后面提前需求,或者撕逼了,你就完了。。
    RainFinder
        53
    RainFinder  
       2018-01-22 09:43:40 +08:00
    签到不应该是按天的吗,一天签 30 次这个月就结束了?
    cgb1021
        54
    cgb1021  
       2018-01-22 11:45:07 +08:00
    按时间排序不就搞定了吗
    mingl0280
        55
    mingl0280  
       2018-01-22 21:33:34 +08:00 via Android
    没必要删吧……
    另外这个是“队列”,FIFO 的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   984 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 1610ms · UTC 23:01 · PVG 07:01 · LAX 15:01 · JFK 18:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.