V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
LoremIpSum
V2EX  ›  程序员

阿里巴巴技术手册:单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表的理论依据?

  •  2
     
  •   LoremIpSum · 108 天前 · 5084 次点击
    这是一个创建于 108 天前的主题,其中的信息可能已经有所发展或是发生改变。

    不少技术文章都直接引用了这个观点,但没说为什么?有大佬解释下这个理论依据吗?

    48 条回复    2022-10-17 15:01:13 +08:00
    zhilincom
        1
    zhilincom  
       108 天前
    听说 MySQL 单表超过 1000 万行性能会急剧下降。
    akira
        2
    akira  
       108 天前
    这应该是个经验数字,不一定绝对对。 但是如果你只有几十 几百万的数据,就大概率是直接用就好,不需要考虑那么多事情
    dayeye2006199
        3
    dayeye2006199  
       108 天前 via Android
    可能和 b 树的深度,和 Page 的大小有关
    wxf666
        4
    wxf666  
       108 天前   ❤️ 1
    反正 20 天前,在一个 [帖子]( https://www.v2ex.com/t/882773 ) 里,有很多人反映,MySQL 单表存 1~2 亿(#11 楼 #16 #18 #19 #21 #35 )、4 亿(#27 )、10 亿(#36 )、20 亿(#28 )都没问题,查询也很快(< 10 ms ,#27 #28 )
    wxf666
        5
    wxf666  
       108 天前
    我在那个帖子里的 3 楼,也问了个类似的问题,也给出一点猜测(但没人理我。。)
    chendy
        6
    chendy  
       108 天前   ❤️ 4
    1. 经验数字
    2. 阿里(也许)自己有足够完善的组建处理分库分表
    3. 阿里(也许)可以通过传播这个数字,卖更多的数据库或者其他服务
    liuzhaowei55
        7
    liuzhaowei55  
       108 天前 via iPhone   ❤️ 1
    备份、恢复数据的难度,太大了也是灾难
    GTim
        8
    GTim  
       108 天前
    很多业务,估计一个小时就要分一次表了
    makelove
        9
    makelove  
       108 天前
    才 500 万,哪怕机械硬盘时代都毫无问题,更别提现在的高速 SSD
    jorneyr
        10
    jorneyr  
       108 天前
    分库分表没那么好玩,应用端需要精心设计,不能像单库那样随心所欲的写 SQL 。
    Maboroshii
        11
    Maboroshii  
       108 天前 via Android
    之前有人说是 2000w 行,查了一下是索引数深度的效率相关
    sadfQED2
        12
    sadfQED2  
       108 天前 via Android
    @jorneyr 可以加一个 db proxy 层,这一层屏蔽分表分库细节,你代码里面依然可以当单表使用,随心所欲的写 sql 。
    bthulu
        13
    bthulu  
       108 天前   ❤️ 1
    那是说的机械硬盘经验值, 还是偏保守的那种.
    现在的 M.2 SSD, 三星 980PRO, 随机 4k 读写速度是普通机械的 500 倍往上, 同样的, 500 万*500=25 亿, 也就是说, 保守点估计 25 亿行数据再考虑分库分表, 胆子大一点的, 100-1000 亿行数据以上再去考虑这个问题.
    jorneyr
        14
    jorneyr  
       108 天前
    @sadfQED2 分布式数据库一般都有 DB Proxy 的,但是 SQL 落到多个库,数据量大的时候,Proxy 每个节点都取数据来处理的时候,一是慢,二是容易内存超量,例如有 1024 个节点,要查询 1000 行,不巧写的 SQL 没有分片键,那么就要去这 1024 个节点上各自都获取 1000 行数据,Proxy 得到 1024 * 1000 行数据进行 Merge Sort ,然后再判断一次取出合适的 1000 行。

    最直观的是使用 Sharding Sphere ,或者看看 TDSql 等的设计文档,没那么自由。
    Biggoldfish
        15
    Biggoldfish  
       108 天前
    一张 table 2GB 就性能下降到不可接受了,怕是在用十年前的 DB 吧
    lmshl
        17
    lmshl  
       108 天前
    老民科八股文了,遗毒万年
    生产环境近两亿行的主表,0.2ms 查询时间,分库分表?分个 J2
    lmshl
        18
    lmshl  
       108 天前
    我怀疑写八股文和背八股文的人不懂什么是 O(log(n)),就硬背树深了一层

    健康项目中:低效率查询,未命中索引的查询应该在 Code Review 阶段被驳回的。过早期的分库分表还会极大提高总持有成本,百害而无一利。因为只需要简单的主从读写分离架构就可以支撑到数万 TPS 了。
    dog82
        19
    dog82  
       108 天前
    这应该是个经验之谈。主要是看表怎么用,如果仅仅是主键查询 10 亿都不要分表。
    ration
        20
    ration  
       108 天前 via Android
    什么数据库,什么版本,硬件性能咋样,如果是 mysql 用的是什么引擎,条件不充分都是空谈。我觉得测试之后才能有结果,真正实践的话也要对数据库进行测试。
    reter
        21
    reter  
       108 天前
    物理定律还有适用条件呢,更何况数据库的访问模式不同,硬件、软件也会不断地迭代和优化
    dog82
        22
    dog82  
       108 天前
    分表并不会让事情变得更简单,仅仅是用逻辑复杂度代替空间复杂度而已
    murmur
        23
    murmur  
       108 天前
    @lmshl 是不是民科不重要,重要的在于程序员的素养,如果考虑到外包团队普遍拉垮的质量,以及 java mysql 这些在企业应用中的高占比,我赞同 500w 分表
    JohnBull
        24
    JohnBull  
       108 天前
    应该没这么夸张。
    自建的文件元数据索引表没能正确处理符号链接 loop ,结果整出来几百 G 的表,直到手工执行 count(*)的时候才发现不对劲,其它操作基本无感
    yohole
        25
    yohole  
       108 天前
    应该是性能目标不一致造成的错觉

    [查询没有问题] 这个本身就很主观的东西,不同企业不同场景对 [查询没问题] 的定义可以差很大的啊

    其他企业敢说自己的查询目标要求与阿里场景和要求一致吗?
    iseki
        26
    iseki  
       108 天前
    阿里的技术手册,其他实体应当仅供参考。
    0576coder
        27
    0576coder  
       108 天前
    之前生产环境有张过亿的表,其实表大了 查询还好,插入更新的时候,cpu 磁盘都会飙升,而且索引建的不科学的话,大表真的是噩梦,大表再数据插入的时候,还不稳定,时间慢,所以我感觉查询并不是分库分表的原因
    这种情况在数据千万级别的时候就慢慢开始显现,但是这个 500W 的数字我也不知道怎么得出的
    mmdsun
        28
    mmdsun  
       108 天前
    过亿有索引的查询肯定没问题。

    有没有人试过修改、更新、和连表的性能?
    0576coder
        29
    0576coder  
       108 天前
    @mmdsun insert 跟 update 的时候会有问题 如果 update 的范围过大 可能该表就卡住了一样 而且时间还不稳定 尤其是索引多一点的时候 简直是噩梦
    Leviathann
        30
    Leviathann  
       108 天前
    查单条肯定随便过亿,其他操作我擦我不好说
    romisanic
        31
    romisanic  
       108 天前
    实际工作中遇到过表数据超过两千万的情况,没有分表,是公司内 IM 的聊天记录。
    结论是:查询、插入,以及主键更新,甚至索引做的不错,条件查询、翻页也还可以。
    但是:开发新功能时,表结构变更,一个不注意,就是灾难。变更一次锁表 20 分钟。
    Valid
        32
    Valid  
       108 天前
    表设计的垃圾才需要
    Jooooooooo
        33
    Jooooooooo  
       108 天前
    这当然是经验只谈.

    几百万的表, 单表查基本没事.

    越大单表风险越大, 还是趁早拆.
    victorc
        34
    victorc  
       108 天前
    它就是随便一说,不要这样机械,一旦启用分表,你的程序也要对应的修改,分表的好处是:系统具备横向扩容的能力. 流量大幅度上涨之后,加点机器就能抗住,如果没有这个需求就不需要扩

    只要硬盘够大,单表存放数量随便
    shiny
        35
    shiny  
       108 天前
    小马过河,自己趟一趟才知道深浅。索引做得如何、SQL 复杂度、硬件配置、每行数据的数据量都会对结果有影响。有十几亿记录数的表也跑得欢,也遇到过百万的表就已经很慢。
    tohuer00
        36
    tohuer00  
       108 天前
    分表分库这些都是有代价的,分了以后业务开发难度会明显增大,越复杂的业务越是如此。
    很多公司负责技术架构的人并不参与业务开发,说得不好听,为了自己的 KPI ,纸上谈兵拍脑袋定方案,害人不浅。

    分不分表,怎么分,都要看具体业务和原有设计。
    HankLu
        37
    HankLu  
       108 天前
    超过 500 万行或 2GB 才推荐,也就是说不超过 500 万行或 2GB ,不推荐分表,因为完全没有这个必要。
    cbdyzj
        38
    cbdyzj  
       108 天前 via Android
    我们公司以前是 800w 行,但实际生产上也有超过 4000w 行的表跑着
    someonedeng
        39
    someonedeng  
       108 天前
    甚至没提硬件。。就嗯背八股
    aptupdate
        40
    aptupdate  
       108 天前 via iPhone
    我记得 oracle 是 1 亿,mysql 不至于这么拉胯吧?
    sean424
        41
    sean424  
       107 天前
    12 年的时候,mysql 免费版 大概 600 多万 数据是个分界线
    keakon
        42
    keakon  
       107 天前
    InnoDB 的一页默认是 16KB ,其中有 100 多字节是头部等不用于存储数据的,这里先忽略。
    索引页的每行要存储一个主键(假设是 int ,4 字节)和一个页号( 4 字节),共计 8 字节。即一页最多存储 2K 条。
    以一个 3 层的 B+ 树来计算,前两层是索引页,最多索引 2K * 2K = 4M 个节点。
    假设表的每行占用的空间是 1KB ,那么一个数据页(叶子节点)最多存储 16 条数据,所有节点共可以存储 64M 条数据( 64GB 大小)。
    超过这个量时,要用 4 层的 B+ 树,那么 IO 次数就至少多出 1/3 ,索引也很难全放在内存中,肯定会大幅影响性能。

    但是题目中提到的 500M 行和 2GB 并不是一个固定值,如果主键和每行占用的空间较小,就能存放更多的页。甚至你还能修改 innodb_page_size ,配置成更大的页,以在一页中存储更多行(但是可能造成 IO 的浪费,因为每次至少读一页)。
    lazyfighter
        43
    lazyfighter  
       107 天前
    @keakon 非常赞
    sun1991
        44
    sun1991  
       107 天前
    之前一个人能搞定, 分表后需要一个团队维护. 对部门有利.
    daoqiongsi1101
        45
    daoqiongsi1101  
       107 天前
    我们存了十几亿数据,看你怎么查,不是所有查询都会很慢
    Seulgi
        46
    Seulgi  
       107 天前
    阿里人家数据库实例是什么规格都没给你说, 你怎么确定自己的实例规格要按照 500w 或 2GB 来呢, 阿里的技术手册, 就看看就行吧. 经验值始终要去躺一次才知道什么效果, 没必要强硬生套.
    cubecube
        47
    cubecube  
       107 天前
    @wxf666
    1. 十年前的 mysql 的确不太行( 5.7 之前)
    2. 十年前的 CPU 性能瓶颈也很大,不分库存在 CPU 瓶颈
    3. 之前的 Disk 是 HDD ,现在大部分是 ssd ,导致数据库性能有急剧提升。
    综上,以前的观点和现在大家的体感不一致很正常。
    motecshine
        48
    motecshine  
       107 天前
    我们单表 670GB 数据 OLTP 查询 基本在 20-30ms
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   1835 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 12:02 · PVG 20:02 · LAX 04:02 · JFK 07:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.