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
vloony
V2EX  ›  MySQL

摇号系统如何快速确定空值

  •  
  •   vloony · 2018-07-14 03:22:24 +08:00 · 3786 次点击
    这是一个创建于 2360 天前的主题,其中的信息可能已经有所发展或是发生改变。

    mysql 摇号系统如何更有效率的确定 10000-99999 之间的未使用的值

    现有方案是从随机一个数开始,查询是否占用》占用+1 继续查询 直到没有占用

    效率非常低 数据库经常挂 有什么高效率的查询方法 求大神指导

    16 条回复    2018-07-17 13:06:16 +08:00
    34C
        1
    34C  
       2018-07-14 03:41:21 +08:00 via iPhone   ❤️ 1
    空间换时间,先把所有的号记录到数据库,摇号的时候 select 未使用的 并且随机排序
    chengluyu
        2
    chengluyu  
       2018-07-14 04:08:52 +08:00
    1L 的答案足够了。数据范围很大的话可以考虑用个非平凡哈希函数。
    yangqi
        3
    yangqi  
       2018-07-14 04:11:33 +08:00
    不连续的没有高效的办法,最好的就是增加一个连续的 id 专门用来摇号。
    GoPython
        4
    GoPython  
       2018-07-14 05:50:18 +08:00 via Android
    为什么我一看到题目就先想到加载到 redis 缓存?
    wenzhoou
        5
    wenzhoou  
       2018-07-14 07:30:22 +08:00 via Android   ❤️ 1
    楼主,你现在这个方案,完全重定义了随机,知道不?
    atcdef
        6
    atcdef  
       2018-07-14 07:41:56 +08:00
    一共才不到 10 万个整数,python 直接生成这样一个列表,random.choice,再从列表里删了,就行了。
    leafleave
        7
    leafleave  
       2018-07-14 07:45:07 +08:00 via iPhone
    摇到一个值后,把它从原数据库里面删除再摇
    zcjfesky
        8
    zcjfesky  
       2018-07-14 07:49:26 +08:00 via Android
    你这个“查询到不占用就设为占用”的需求让我觉得你为什么不直接随机打乱数组然后从头到尾输出整个数组…
    opengps
        9
    opengps  
       2018-07-14 08:14:14 +08:00 via Android
    1 楼方案可以,先查出来所有的空号,然后用空号去随机
    eslizn
        10
    eslizn  
       2018-07-14 09:07:13 +08:00
    就楼主说的这个量级且只使用 mysql 的情况下可以考虑下这种做法
    UPDATE table SET user_id = 当前用户 id WHERE user_id = 0 ORDER BY RAND() LIMIT 1;
    lihongjie0209
        11
    lihongjie0209  
       2018-07-14 10:03:56 +08:00
    最简单的: 首先生成 10000-99999 所有的数字, 随机打乱, 插入数据库. 用的时候取第一条并删除. 如果使用失败, 那么就添加到数据库的最后一条.

    用数据库主要是为了持久化, 然后模拟一个 queue 就可以了
    reus
        12
    reus  
       2018-07-14 10:08:03 +08:00
    update numbers
    set used = true
    where num = (
    select num from numbers
    where not used
    order by random()
    limit 1
    )
    returning num
    qiayue
        13
    qiayue  
       2018-07-14 10:12:42 +08:00   ❤️ 1
    @lihongjie0209 最近刚做完一个抽奖 H5,总共才 2 万个奖品,我就是先生成 2 万条记录,乱序后插入数据库,用的时候,每次去一条。

    这种方式就像彩票店的刮刮奖,彩票事先生产制作出来了(理想情况,大奖没有被事先拿出),并且也是打乱顺序的
    lihongjie0209
        14
    lihongjie0209  
       2018-07-14 10:17:21 +08:00
    @qiayue #13 对的
    zjqzxc
        15
    zjqzxc  
       2018-07-14 11:03:50 +08:00
    位图法
    遍历一遍,根据 id 生成一个 bitmap,若为 0 就是对应的 id 为空,为 1 就是占用
    九万个记录,一共 11.25KB,放内存轻轻松松。

    如果以后经常要用,加入新记录到时候同时操作下这个 bitmap 即可
    vloony
        16
    vloony  
    OP
       2018-07-17 13:06:16 +08:00
    感谢所有回复的提供解决方案的人~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1345 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 17:19 · PVG 01:19 · LAX 09:19 · JFK 12:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.