V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cjbi
V2EX  ›  数据库

一般用户表的用户 ID,是不是设计成字符串的比较多

  •  
  •   cjbi · 2023-03-01 13:17:49 +08:00 · 4867 次点击
    这是一个创建于 667 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,请说明理由,表关联也是用字符串吗?

    Chad0000
        1
    Chad0000  
       2023-03-01 13:21:34 +08:00 via iPhone
    整型自增。

    放心,系统下线了用户都不会有那么多。
    zoharSoul
        2
    zoharSoul  
       2023-03-01 13:23:52 +08:00
    不是, 基本都是整形
    shyangs
        3
    shyangs  
       2023-03-01 13:30:06 +08:00
    別和百度貼吧踩同一個坑。

    哪天產品拍腦袋, 說百度帳號(用戶名)要可以讓使用者自由地更名, 你要學貼吧在 username 裡加各種符號避免重複?
    shyangs
        4
    shyangs  
       2023-03-01 13:34:10 +08:00   ❤️ 3
    承上,所以區分 id 和 name,

    id 用整型自增,系統決定,使用者不可更改 id ,只能改 name 。
    justfindu
        5
    justfindu  
       2023-03-01 13:36:32 +08:00
    自增, 如果你要避免被扫, 那就 uuid 呗
    op351
        6
    op351  
       2023-03-01 13:36:40 +08:00
    因为用主键的整型自增列会暴露其他用户,所以不会用主键的整型自增列
    而是自增列之外设计一个单独的用户 ID 列 使用三方库根据日期之类的生成不会重复的字符串
    xiaoliu926
        7
    xiaoliu926  
       2023-03-01 13:44:28 +08:00
    @op351 我这边的项目都是雪花算法生成主键 id 的,安全的很
    LeegoYih
        8
    LeegoYih  
       2023-03-01 13:48:38 +08:00
    bigint
    实际接口都会鉴权,不存在通过 ID 被暴力遍历的情况
    op351
        9
    op351  
       2023-03-01 13:54:13 +08:00
    @xiaoliu926
    不用整型自增就行
    我也是之前用 fiddler 分析某 app 的接口才意识到直接使用自增会导致用户信息泄露-。-
    NoKey
        10
    NoKey  
       2023-03-01 13:57:38 +08:00
    有时候对外叫 userID ,他实际不是 id ,用户 id ,要区分业务层面的 id ,和数据层面的 id ,你讲的是哪一个?😆
    cjbi
        11
    cjbi  
    OP
       2023-03-01 14:00:21 +08:00
    @NoKey 上面都提到了,主要怕被看出规则,我目前有个项目是用自增做关联字段,另外弄个字段+随机字符串作为用户唯一 ID ,总感觉很奇怪
    chendy
        12
    chendy  
       2023-03-01 14:05:51 +08:00
    自增,怕被爆破就在接口层加一层编码规则处理,变成火星文(比如加上固定前后缀然后取字节然后翻转然后 base64 啥的)
    superedlimited
        13
    superedlimited  
       2023-03-01 14:09:25 +08:00
    为什么 mongodb 自动生成的_id 是一串字符串呢
    abelyao
        14
    abelyao  
       2023-03-01 14:09:45 +08:00
    已经习惯了能用 uuid 就用 uuid 了,或者 nanoid - https://github.com/ai/nanoid
    god7d
        15
    god7d  
       2023-03-01 14:10:55 +08:00 via iPhone
    guid
    melkor
        16
    melkor  
       2023-03-01 14:11:14 +08:00 via iPhone   ❤️ 1
    用自增 ID 的这些建议,不考虑横向 sharding 问题吗?雪花生成全局唯一 ID 就行了
    fiypig
        17
    fiypig  
       2023-03-01 14:13:10 +08:00
    我第一家公司就用字符串的 用户账号, 现在的用自增,也有用 UUID ,我还没遇到过。。
    manasheep
        18
    manasheep  
       2023-03-01 14:13:59 +08:00
    无脑 GUID ( UUID )就可以了,MongoDB 的话用它自己的 ObjectID 也行
    dk7952638
        19
    dk7952638  
       2023-03-01 14:15:17 +08:00
    id 是给系统用的编码,no 是给人用的编码
    id 最好是自增,如果是分布式可以用雪花算法,自增可以提高数据库性能,还能实现游标分页
    no 一般都是有意义的,比如快递单号
    tool2d
        20
    tool2d  
       2023-03-01 14:17:43 +08:00
    爆破很好处理的,你 api 加密一下就可以了。或者加个一次性访问权限,nonce 那种参数。

    只要索引建的好,字符串查找速度也不慢的。
    LeegoYih
        21
    LeegoYih  
       2023-03-01 14:24:14 +08:00   ❤️ 3
    @superedlimited MongoDB 的 ObjectId 也是根据 Timestamp 和 MachineID 自增的 bigint ,只不过它是 12 字节 96 位的整数,用字符串方便展示
    superedlimited
        22
    superedlimited  
       2023-03-01 14:32:33 +08:00
    @LeegoYih #21 谢谢,我查了一下文档,原来它是 16 进制的数字。我是直接用的 mongodb 的免费 cloud 数据库,还没仔细看文档。
    vitoliu
        23
    vitoliu  
       2023-03-01 14:34:57 +08:00
    BIGINT 毋庸置疑,具体生成规则,看用户 ID 包含不包含对外业务含义,包含对外业务含义生成规则不能包含趋势递增。
    xuanbg
        24
    xuanbg  
       2023-03-01 14:37:17 +08:00
    我选择雪花 ID 。用字符串是什么鬼? UUID ?
    Chad0000
        25
    Chad0000  
       2023-03-01 15:04:42 +08:00 via iPhone
    @melkor
    有太多系统到废弃那天用户到不了那么多。自增没什么不好。
    Chad0000
        26
    Chad0000  
       2023-03-01 15:09:09 +08:00
    @chendy
    @cjbi
    @op351

    有种叫 hashid 的技术你可以了解一下,安全起见你还可以将数组化[id, randomId]这样,第 1 个是真正的 Id ,后面那个是验证码。
    acvrock
        27
    acvrock  
       2023-03-01 15:15:07 +08:00
    BIGINT +1,UID 大概率是其他业务表的索引,越短越好,最好趋势递增
    但是不能简单的自增,否则用户规模会被外部猜测出来,或者被扫描爆破
    pkoukk
        28
    pkoukk  
       2023-03-01 15:19:22 +08:00
    内部系统用数据库自增
    对外系统用雪花,UUID 太长了,占存储太多了,而且最主要的坑是如果拿 uuid 当主键,插入性能太差了
    虽然用户不太可能用户注册有太高并发,但是如果你需要用备份恢复一个库或者增加一个从库的时候就要疯
    chendy
        29
    chendy  
       2023-03-01 15:26:00 +08:00
    @Chad0000 学习了,原来有现成的东西可以用
    allinoneok
        30
    allinoneok  
       2023-03-01 15:30:51 +08:00
    如果你的 ID 需要写入 cookie 并加密就选择随机生成 id
    melkor
        31
    melkor  
       2023-03-01 15:40:59 +08:00 via iPhone
    @Chad0000 直接用雪花成本也不算高,关键是一旦要 sharding 那就很痛苦了,成本太高
    RICKEYGONG
        32
    RICKEYGONG  
       2023-03-01 15:47:34 +08:00
    Guid userId = new Guid();
    leeraya
        33
    leeraya  
       2023-03-01 15:52:56 +08:00
    bigint 够够的
    b821025551b
        34
    b821025551b  
       2023-03-01 15:53:26 +08:00
    @melkor 雪花成本应该是最高的,在大部分引擎下,无序主键会导致查询性能降低,以及空间浪费
    youisme
        35
    youisme  
       2023-03-01 15:57:23 +08:00
    @b821025551b 雪花算法是有序的
    afstyle
        36
    afstyle  
       2023-03-01 16:03:16 +08:00
    @b821025551b 建议你好好看看雪花 id 算法
    Ashore
        37
    Ashore  
       2023-03-01 16:08:18 +08:00 via Android
    你离职了以后都不会有那么多的用户的。放心吧
    cnbattle
        38
    cnbattle  
       2023-03-01 16:10:56 +08:00
    推荐雪花 id , 需要注意的数 如果前端是 js ,json str 转 json 对象 数字 大于 17 位时会丢失精度 得前端或后端特殊处理下
    karloku
        39
    karloku  
       2023-03-01 16:14:10 +08:00
    字符串的索引性能不行, 作为主键还是用整型好

    不管是 mongodb 的 ObjectId 还是 UUID 本质上也只是被表示为 16 进制的定长 bits, 在数据库里可以用 binary(12) 或者 binary(16) 存取. mysql8 里有直接用于转换字符串的函数 `UUID_TO_BIN()` / `BIN_TO_UUID()` 和生成用的 `UUID()` . postgres 则是直接支持 uuid 类型的字段, 支持在 sql 里用字符串进行写入和查询.
    不需要满足可排序性的时候可以用 uuidv4. 需要满足可排序性的时候可以用 mongodb 的 ObjectId 和 128 位的 ulid.
    litchinn
        40
    litchinn  
       2023-03-01 16:16:29 +08:00
    准确来说,雪花算法那个叫单调递增。
    参与的有一个项目,最开始是自增,但是后面有个客户有个需求,他部署了两套系统,A 、B ,但是每天要将 B 系统的数据全部同步到 A ,然而这些数据里有关联 id ,于是只能改成雪花算法生成的 id ,bigint
    也用过字符串类型的 id ,但是因为没办法单调递增且自己 debug 很不方便所以个人并不喜欢
    目前使用雪花算法 id ,数据库 bigint 并且设置自增
    BeforeTooLate
        41
    BeforeTooLate  
       2023-03-01 16:34:15 +08:00
    整数自增问题用户容易被爬虫遍历吧,比如你是 id1 ,我是 2 ,只要一个个试过去就行了
    liuidetmks
        42
    liuidetmks  
       2023-03-01 17:13:16 +08:00
    @BeforeTooLate 不成熟的想法,自增一个比较大的素数就行了。uint64 溢出也不要紧,正好相当于取模了
    realpg
        43
    realpg  
       2023-03-01 17:19:42 +08:00
    unsigned uint64 自增
    多库分布系统就他自己自增 然后复合唯一索引带 node_id ,合并一起做 userid
    realpg
        44
    realpg  
       2023-03-01 17:20:28 +08:00
    @BeforeTooLate
    数据库 ID 和前端显示 ID 为什么要统一?
    发送前和获取后过一个 o(n)复杂度的简单变换,别人不知道算法就完事
    Danfi
        45
    Danfi  
       2023-03-01 17:24:24 +08:00 via Android
    数据库查询用 bigint ,对外输出 hashid
    hulala1021
        46
    hulala1021  
       2023-03-01 17:31:07 +08:00   ❤️ 1
    职业生涯遇到过好几次数据库迁移,得到的教训就是数据库尽量不要用自增 id ,不然迁移表数据简直是灾难
    polo3584
        47
    polo3584  
       2023-03-01 17:58:01 +08:00
    区分 uid 和 uname 就行
    zzzzz001
        48
    zzzzz001  
       2023-03-01 20:39:49 +08:00
    @BeforeTooLate 平时写接口注意点,带上当前登录人的标记去数据库查,只查当前登录人的信息,不就避免被刷了吗。这样的思路很多
    ccagml
        49
    ccagml  
       2023-03-01 20:46:58 +08:00 via Android
    用户 id 直接数据库自增?都不分表的吗?
    lovelylain
        50
    lovelylain  
       2023-03-01 20:53:03 +08:00
    整型自增,对外加密,就像微信的 openid 一样,虽然不清楚具体实现,但应该是可以解密得到整型自增 uid 的
    lovelylain
        51
    lovelylain  
       2023-03-01 20:56:06 +08:00
    @ccagml 分库分表也可以自增呀,例如百库十表,取 uid 低 10 位标识在哪个表,右移 10 位得到在具体表中的自增 id
    hsuyeung
        52
    hsuyeung  
       2023-03-01 22:31:06 +08:00 via iPhone
    bigint ,然后对外 hashid
    wangritian
        53
    wangritian  
       2023-03-01 22:52:04 +08:00
    用了很多年 uuid ,完全代替了自增数字,并且封装在所有使用过的框架中
    除了一点点性能问题,好像没什么缺陷了吧
    zhaogaz
        54
    zhaogaz  
       2023-03-01 23:12:24 +08:00
    看需求吧。。

    首先看你这个用户 id 定义成什么,还有就是个人习惯,公司习惯,代码项目习惯啥的。

    有的是 us-xxxxx ;有的是 uuid ;有的是自增数;有的是长整数,这和 是不是字符串都没关系。。。

    你想问的是数据库的实现,和 用户 id 设计没啥关系。。数据库层面,一般用 固定 char 就行。。你数据库存成数字有什么优势么?你想一想

    然后再解释下自增 id:自增 id 相当于把 id 生成的事情扔到 db 了。看你们个人习惯和项目习惯,不是不可以。如果数据关联的逻辑也扔给 db ,这么做都没啥问题。

    其实都挺新手的问题,大概能猜到 op 工作环境。
    twofox
        55
    twofox  
       2023-03-01 23:38:17 +08:00
    无脑雪花主键啊。。UUID 不建议,太长和分散,不适合索引
    cjbi
        56
    cjbi  
    OP
       2023-03-02 00:15:40 +08:00
    @zhaogaz 你牛逼,这都能扯到工作环境
    ZhiyuanLin
        57
    ZhiyuanLin  
       2023-03-02 11:21:48 +08:00
    为了防爬虫丢掉自增 ID 有点小题大做了,用户量不大的话完全可以给进出 API 接口的自增 ID 跑个对称加密,防爬+性能兼得。这年头 AES 加解密的开销比 DB lookup 一个字串 ID 小多了。
    wind8866
        58
    wind8866  
       2023-03-02 12:00:01 +08:00
    用字符串作为 ID 的要注意一下数值特别大的情况,接口返回 JSON 格式时要用程序转成字符串,别超过最大安全数。吃过这方面的亏
    melkor
        59
    melkor  
       2023-03-02 17:32:01 +08:00 via iPhone
    @b821025551b 主键都是聚簇索引,都排好序的,为啥会影响读性能?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2812 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:30 · PVG 19:30 · LAX 03:30 · JFK 06:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.