数据库中 id 字段存在的必要性 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
qyz0123321
V2EX    数据库

数据库中 id 字段存在的必要性

  •  
  •   qyz0123321 2015-08-22 13:57:56 +08:00 3627 次点击
    这是一个创建于 3721 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在公司设计数据库的时候,有人提出来了在设计数据库的时候直接使用中文名字作为主键,表之间的关系也直接用中文名字作为主键(中文名字不重复)。
    这样做的好处当然是数据库方便易读,易于理解,但是这样做势必会保证搜索速度下降(我是这么认为的),增大数据库的大小。
    但是不知道现在的 mysql , mssql 数据库对中文做的优化能不能抵消搜索的劣势?有没有使用中文作为主键的场景?
    刚刚毕学生,求轻喷。。

    第 1 条附言    2015-08-22 15:30:05 +08:00
    呃,没写明白,字段名必然是英文的。中文是指用字段值为中文的字段作为主键。
    第 2 条附言    2015-08-22 16:52:41 +08:00
    刚刚还想到一点,用 id 的话,要是前端接口也用 id 作为参数的话,那么接口有被穷举的可能。。
    34 条回复    2015-08-23 16:08:00 +08:00
    haogefeifei
        1
    haogefeifei  
       2015-08-22 14:08:06 +08:00
    优化某字段的查询速度,加索引啊。。。
    loading
        2
    loading  
       2015-08-22 14:08:14 +08:00 via Android   1
    我的 sessionId 就是用数据库的 id ,每次都要验证,这还是能快很多的。
    est
        3
    est  
       2015-08-22 14:09:20 +08:00   1
    innodb 来说,你不弄 id 也会有个隐式 PK 的。

    中文主键没啥性能问题,都是二进制数据。
    powergx
        4
    powergx  
       2015-08-22 14:09:22 +08:00 via iPhone
    考虑以后有改名字的需求怎么办
    qyz0123321
        5
    qyz0123321  
    OP
       2015-08-22 14:28:04 +08:00
    @haogefeifei 嗯,目前查询中文的字段的确是加了索引的,但是找到对应的 id 再去找其他表中对应的字段,用数字的速度应该比中文快很多吧。
    qyz0123321
        6
    qyz0123321  
    OP
       2015-08-22 14:29:46 +08:00
    @est soga ,原来 Innodb 还会内置一个隐藏的 PK 。从单表的性能上来说,那查询那就没啥区别了啊。。
    qyz0123321
        7
    qyz0123321  
    OP
       2015-08-22 14:30:29 +08:00
    @powergx 这个需求的确要考虑。。。一改全都要改了。。
    akira
        8
    akira  
       2015-08-22 15:11:48 +08:00
    个人习惯所有表里面的自增字段都是 id ,这样不会乱也好记

    PS : 字段名尽量避免用中文是个好习惯。
    babyname
        9
    babyname  
       2015-08-22 15:14:26 +08:00
    comment 是干嘛的?中文易于理解?那是团队水平不行。
    iamppz
        10
    iamppz  
       2015-08-22 15:19:14 +08:00 via iPhone
    MySQLdump 按表名备份会悲剧,不知道现在怎么样了
    iamppz
        11
    iamppz  
       2015-08-22 15:19:58 +08:00 via iPhone
    中文字段用 MySQLdump 按表名备份会悲剧,不知道现在怎么样了
    qyz0123321
        12
    qyz0123321  
    OP
       2015-08-22 15:26:59 +08:00
    @babyname 呃,不是字段名,是字段里的值,字段名当然是英文了。
    coolzjy
        13
    coolzjy  
       2015-08-22 15:39:46 +08:00
    id 当然不是必须的,不考虑性能的情况下满足唯一和固定两个条件的字段都能拿来做主键,比方说身份证号
    qyz0123321
        14
    qyz0123321  
    OP
       2015-08-22 16:51:27 +08:00
    @coolzjy 嗯,的确,主键的定义被玩坏了。。
    qyz0123321
        15
    qyz0123321  
    OP
       2015-08-22 16:59:26 +08:00
    @haogefeifei
    @loading
    @est
    @powergx
    @coolzjy

    突然想到,要是表做 inner join 的时候,中文是不是比 id 要慢呢?
    sunmonster
        16
    sunmonster  
       2015-08-22 17:03:53 +08:00
    数据库存在这么多年了,全国成千上万的企业在用,我是重来没见过用中文做主键的,为什么没有人这么用呢,还是说你思维巧妙,第一个想到用中文来做主键索引?有的时候折腾一下可以,千万不要在生产环境实践,不然会被问候全家的。
    qyz0123321
        17
    qyz0123321  
    OP
       2015-08-22 17:23:27 +08:00
    @sunmonster 呃。。只是突发其想讨论一下合理性和性能之类的。。求轻喷。。
    haogefeifei
        18
    haogefeifei  
       2015-08-22 17:29:35 +08:00
    没有作死用过中文做主键的表示不说话。。。。 中文字段例如用户名什么的加个唯一约束就好。。。。
    em70
        19
    em70  
       2015-08-22 18:05:39 +08:00 via Android
    只要你能保证每条记录的唯一性,不要 ID 字段也行啊。做不到唯一的话, ID 字段自增是最方便的
    jiangzhuo
        20
    jiangzhuo  
       2015-08-22 18:19:12 +08:00
    中文名字不会重复??李超表示理解不了
    jianyunet
        21
    jianyunet  
       2015-08-22 18:45:35 +08:00   1
    @qyz0123321 你考虑的问题已经有过很多讨论了,典型的逻辑主键和物理主键问题

    用含有物理意义的字段做主键,需求变更会比较难办,或者举个简单的例子,楼上也提到过了,你能保证身份证真的是唯一的吗?人家就有发错的怎么办?
    kiwi95
        22
    kiwi95  
       2015-08-22 19:08:16 +08:00
    id 做主键比较好,中文名加个唯一约束,加索引吧。 id 做主键有很多方便的地方
    E2gCaBAT5I87sw1M
        23
    E2gCaBAT5I87sw1M  
       2015-08-22 19:11:11 +08:00   1
    qyz0123321
        24
    qyz0123321  
    OP
       2015-08-22 19:21:45 +08:00
    @jianyunet 明白了,谢谢
    glasslion
        25
    glasslion  
       2015-08-22 23:07:31 +08:00
    很多 ORM 在实现上就要求数字自增主键
    aspirin2d
        26
    aspirin2d  
       2015-08-22 23:22:10 +08:00
    mongodb 表示,根本没得选, id 就是文件名 -_-P
    karloku
        27
    karloku  
       2015-08-22 23:32:39 +08:00   2
    id 最好是一个 和业务无关, 不会重复的数字. 至于是不是自增整型这不重要.
    id 的意义就在于无论业务如何变化, 记录的内容如何变化, 都可以唯一标识这一条记录.

    至于楼主最后说的被枚举, 这个不需要担心. 现在大家分布式系统用的多, id 的生成规则也会比较复杂. 像是分布式数据库常用的机器 hash+进程 hash+时间戳 hash+本地自增序列拼出 32 位乃至 64 位整型, 这个要枚举先过 ddos 防护这一关
    Youen
        28
    Youen  
       2015-08-22 23:54:07 +08:00
    我觉得这个问题和 id vs guid 作为主键的问题有些相似。
    LPeJuN6lLsS9
        29
    LPeJuN6lLsS9  
       2015-08-23 00:03:41 +08:00
    @glasslion 你说的“很多”有哪些?很多 ORM 没有你说的要求,比如 django 自带的和 SQLAlchemy ,小的有 peewee 。

    我有见过这种情况:只加了一个代理 PK ,而对于真正的 key 却连 UNIQUE 都不加(在这里是一个类似 UUID 的 varchar )
    msg7086
        30
    msg7086  
       2015-08-23 03:58:55 +08:00   1
    @karloku 一直到 27 楼才终于有人点出这句话我也是醉了。

    主键的作用就是永久有效地标示这唯一一条记录,最好与业务无关。

    @hantsuki 类似 UUID 的 varchar 其实加不加 UNIQUE 没区别。 UUID 本身撞 ID 的几率就小得不行[1],不需要考虑唯一性。

    [1]: https://zh.wikipedia.org/wiki/通用唯一识别码#.E9.9A.A8.E6.A9.9FUUID.E7.9A.84.E9.87.8D.E8.A4.87.E6.A9.9F.E7.8E.87
    Cloudee
        31
    Cloudee  
       2015-08-23 12:44:27 +08:00 via iPhone
    作为索引的话,中文谁不会慢的,但是, varchar 会慢...考虑到大部分情况中文都是放在 varchar 字段里的,很多人就觉得中文慢了
    LPeJuN6lLsS9
        32
    LPeJuN6lLsS9  
       2015-08-23 13:13:34 +08:00
    @msg7086 “总之先来个 id ”在生产时确实很通用,不得不承认……

    如果不用关系数据库提供的其他方法保证数据的完整性,这个 id 其实就是个 rownumber 。如果其他地方都不会用 id 引用这条记录,那不如让数据库自己隐式加上
    msg7086
        33
    msg7086  
       2015-08-23 14:35:42 +08:00   1
    @hantsuki 感觉你说反了。
    既然总要有个 ID ,那不如你自己加上。免得以后业务需要 ID 的时候再去加一个。
    同时自己加的 ID 还可以跨平台跨环境,不用考虑数据库之间的不同实现。
    chenjf2k
        34
    chenjf2k  
       2015-08-23 16:08:00 +08:00
    建议主键命名:表名+ID
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4012 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 00:08 PVG 08:08 LAX 17:08 JFK 20:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86