V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
hanshijun
V2EX  ›  数据库

用 uuid 和自增作为主键,各有什么有缺点呢?

  •  
  •   hanshijun · Oct 19, 2018 · 10055 views
    This topic created in 2758 days ago, the information mentioned may be changed or developed.

    萌新请教,大佬轻喷⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄

    38 replies    2018-10-21 10:54:47 +08:00
    qq976739120
        1
    qq976739120  
       Oct 19, 2018
    单击就用自增吧,分布式有并发的话可以用雪花算法生成主键,也是现成的
    lihongjie0209
        2
    lihongjie0209  
       Oct 19, 2018
    uuid debug 的时候你就难受了
    opengps
        3
    opengps  
       Oct 19, 2018 via Android
    先随口说 2 点,~
    自增 id 容易被猜解,爬虫,跨权限泄露数据比较容易
    uuid 太长,并且有索引碎片,索引多占用空间的问题
    robot777
        4
    robot777  
       Oct 19, 2018
    那生产环境分布式数据库用什么方式好呢,自建一个生成自增 id 的分配服务吗
    rogwan
        5
    rogwan  
       Oct 19, 2018 via Android
    一般应用自增足够,那点数据,规律还用猜吗?大数据 分布式按需使用,uuid 都有四五种。
    zjp
        6
    zjp  
       Oct 19, 2018 via Android
    MySQL 的主键不是递增 /减会有性能损失
    单机下用雪花算法也不错,递增 & 没有明显规律
    lastpass
        7
    lastpass  
       Oct 19, 2018 via Android
    自增 ID 方便排序,获取上 /下节点。而且一般自增 ID 都足够短。
    mortonnex
        8
    mortonnex  
       Oct 19, 2018
    @opengps 索引碎片是什么
    qichengzx
        9
    qichengzx  
       Oct 19, 2018   ❤️ 1
    顺势安利一波:Go 实现的高性能全局唯一序列号生成服务 https://github.com/qichengzx/seqsvr
    思路来自:干货 | 分布式架构系统生成全局唯一序列号的一个思路 https://mp.weixin.qq.com/s/F7WTNeC3OUr76sZARtqRjw

    求 star。
    opengps
        10
    opengps  
       Oct 19, 2018
    @mortonnex 索引碎片这个东西我理解也不是很透彻,你可以自行查询下,我可以确定的是 uuid 确实会有这个问题
    rogwan
        11
    rogwan  
       Oct 19, 2018 via Android
    @mortonnex
    @opengps
    没有删除操作,应该不会产生索引碎片吧
    acr0ss
        12
    acr0ss  
       Oct 19, 2018
    自增方便有序;
    uuid 高并发插入快
    simonliu2018
        13
    simonliu2018  
       Oct 19, 2018
    自增主键(任何有序的序列)插入的时候索引块是连续的,一块写满再创建一块,这样效率显然是很高的。

    如果用无序字段作为主键,索引块要经常分裂、合并(设想一堆无序的数字做插入排序),效率自然就差了。
    simonliu2018
        14
    simonliu2018  
       Oct 19, 2018
    @acr0ss uuid 高并发插入快?原理是?
    xuanbg
        15
    xuanbg  
       Oct 19, 2018
    自增什么都好,就是有两点不好:
    1、分表分库会有 ID 冲突,不分表分库就没有这个问题
    2、外键是啥在主键入库前你不知道,需要插入后查询回来再赋值,这个有点别扭
    kernel
        16
    kernel  
       Oct 19, 2018
    @opengps 自增 id 和被爬是两回事,一个是对内 id,一个是对外,如果需防爬可以再建一列对外 id
    nisekoi
        17
    nisekoi  
       Oct 19, 2018
    自增 id 不单止容易被遍历,还容易暴露你的业务量,另外一点就是以后你数据量大了需要分库分表的时候会有问题
    wps353
        18
    wps353  
       Oct 19, 2018
    1、Innodb 是 B-Tree 结构存储,自增主键能很好的利用连续硬盘空间,uuid 很有可能导致随机 IO 影响效率。
    2、Innodb 中的索引的叶子节点是包含主键的,一般 uuid 都比自增逐渐大,在索引占用空间上自增主键占优势。
    wps353
        19
    wps353  
       Oct 19, 2018
    @acr0ss 你确定并发 uuid 还快?
    lihongjie0209
        20
    lihongjie0209  
       Oct 19, 2018
    @wps353 会快一点, 因为 mysql 内部需要维护一个计数器, 并发访问一定会上锁保护的, 所以获取自增 id 会阻塞
    wps353
        21
    wps353  
       Oct 19, 2018
    @lihongjie0209
    这个 autoinc_lock 可以通过 innodb_autoinc_lock_mode=2 参数 设置来避免,当然这样会导致自增不连续。
    但是 uuid 导致的随机 IO 更有可能是并发效率降低。
    realpg
        22
    realpg  
    PRO
       Oct 19, 2018   ❤️ 1
    @robot777 #4
    我曾经用过这种 MYSQL 自增
    总共生产环境 14 台 MYSQL 订单服务器 架构设计最多兼容 100 台分布式数据库服务器
    每台自增的间隔是 100 BIGINT 类型
    第一台数据库的第一条记录 ORDERID 为 1000001 自增间隔 100
    第二台数据库的第一条记录 ORDERID 为 1000002 自增间隔 100
    以此类推

    每一台服务器的自增 ID 尾数均不相同


    @nisekoi #17
    内部用自增 ID 不代表显示给用户不经过简单变换,直接把数字 ID 暴露给用户只能说设计弱爆了
    比如做一些不吃性能的简单变换法把数字变成字母或者变成另外一组数字
    iPhonePKAndroid
        23
    iPhonePKAndroid  
       Oct 19, 2018
    隐藏业务数量
    derrickT
        24
    derrickT  
       Oct 19, 2018
    自增通常来说应该作为 API 中的参数暴露,容易被遍历获取数据,但是性能好,索引效率高
    UUID 没有什么规律,字符串,索引效率差,但是不会被遍历
    aborigine
        25
    aborigine  
       Oct 19, 2018
    如果是 mysql,自增 id 做主键而且不要用到业务中吧!可以用 uuid 当作 user_id 之类的区分并设成 unique key。原因么,详见高性能 MySQL
    zhzer
        26
    zhzer  
       Oct 19, 2018
    分布式无法自增或者说无法同步,就这点区别,干的事都一样
    Moorj
        27
    Moorj  
       Oct 19, 2018
    我用 UUID
    abcbuzhiming
        28
    abcbuzhiming  
       Oct 20, 2018
    @acr0ss uuid 想和自增 id 比插入快你是不是搞错了什么,uuid 保证的是分布式环境下的唯一性,轮性能别和自增 id 比
    abcbuzhiming
        29
    abcbuzhiming  
       Oct 20, 2018
    @realpg 数字 id 暴露给用户也没啥,关键是要有完善的权限控制系统,数字 id 暴露了就出安全问题明显是设计缺陷
    realpg
        30
    realpg  
    PRO
       Oct 20, 2018
    @abcbuzhiming #29
    并不是,主要是对于自增系统,数字 ID 基本暴露订单量,增量,逻辑关系,对于有心人来说,这非常敏感
    abcbuzhiming
        31
    abcbuzhiming  
       Oct 20, 2018
    @realpg 我很有兴趣,你说说看有心人就算知道了我的订单量和增量,它能干什么,这就好比公司营业额,你知道了又能做啥
    realpg
        32
    realpg  
    PRO
       Oct 20, 2018
    @abcbuzhiming #31
    我随便举点例子,实际上在有心人那里,能做的东西不止这些

    比如你是一个正在吹牛逼拉 C 轮投资的电商,处处造势,日订单量千万,会员三亿,然后被媒体公开,你家 UID 才到九百多万,昨天下单订单号跟今天订单号就差六十多万,完事你家得用多钱去公关这些恶劣影响


    商业企业,自身的数据是最值钱的商业机密之一,通过外部参数判断出你家的很多数据,是重要的数据泄露


    你要说这些都没啥用,那再来个有实际应用的

    公务员报名考试 120 元,很多人愿意花无数个 120 元,就为了摸报名人数
    abcbuzhiming
        33
    abcbuzhiming  
       Oct 20, 2018
    @realpg 666666,果然多听听别人的脑洞对自己有帮助。我认同你的说法
    013231
        34
    013231  
       Oct 20, 2018
    @realpg
    @abcbuzhiming
    這還真不是腦洞, 我碰到過幾乎一模一樣的事. 有人拿個項目來忽悠我們老闆, 然後我發現他的自增 UID 比他宣稱的用戶量少兩個數量級...
    acr0ss
        35
    acr0ss  
       Oct 20, 2018
    @abcbuzhiming

    感谢指出错误

    我只考虑了并发生成的时间,忽略了插入后重排索引的时间
    看来没有诸位老哥了解的透彻,避免误导
    huadi
        36
    huadi  
       Oct 20, 2018
    @realpg 所以自增不能是纯自增。比如每天或者每 2 小时,增加 10000。当然这样有溢出风险,比如 2 小时内新增用户不能超过 10000
    realpg
        37
    realpg  
    PRO
       Oct 20, 2018
    @huadi #36
    我还是支持前台显示变换的方式
    通过 view 层和取回参数时的简单变换
    buliugu
        38
    buliugu  
       Oct 21, 2018
    自增的话可以用 Hashids 处理一下
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   968 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 98ms · UTC 20:21 · PVG 04:21 · LAX 13:21 · JFK 16:21
    ♥ Do have faith in what you're doing.