mysql 的一张表超过 1000w 后,如何优化 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ginux
V2EX    数据库

mysql 的一张表超过 1000w 后,如何优化

  •  1
     
  •   ginux 2019-04-11 14:26:50 +08:00 6817 次点击
    这是一个创建于 2378 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现状: 1.超过 1000w 的表较多; 2.每个表之间会有较多的联表查; 3.一个 select 的 sql 可能需要查处几万条数据; 大伙有啥好方法么?

    48 条回复    2019-07-11 14:52:45 +08:00
    kukumao
        1
    kukumao  
       2019-04-11 14:42:07 +08:00
    分表。。。。
    gz911122
        2
    gz911122  
       2019-04-11 14:45:01 +08:00
    索引 ,尽量别连表
    分区
    rockyou12
        3
    rockyou12  
       2019-04-11 14:49:08 +08:00
    如果是统计类型的业务还是直接用 spark 这些来做吧,反正也可以写 sql
    ggicci
        4
    ggicci  
       2019-04-11 14:52:07 +08:00
    ## 自己扛

    因为业务影响会比较大,所以都需要根据业务按顺序考虑以下思路:

    1. 索引优化
    2. 分区优化
    3. 分库
    4. SQL 查询优化,比如把某些联表查询改造成多次单表查询

    ## 云服务扛

    换个超的关系型数据库产品
    reus
        5
    reus  
       2019-04-11 14:58:01 +08:00
    换 PostgreSQL.
    linxb
        6
    linxb  
       2019-04-11 15:00:46 +08:00
    增加冗余字段,减少连表操作,水平分表
    yangxin0
        7
    yangxin0  
       2019-04-11 15:01:37 +08:00
    删库重来
    babedoll
        8
    babedoll  
       2019-04-11 15:02:13 +08:00
    分表
    jusalun
        9
    jusalun  
       2019-04-11 15:32:06 +08:00
    放 clickhouse,十几亿的量单机都能秒查
    love
        10
    love  
       2019-04-11 15:43:09 +08:00 via Android
    啥叫一条 sql 查几万,需要一次性取出几万条记录?
    goodleixiao
        11
    goodleixiao  
       2019-04-11 16:04:31 +08:00
    先优化业务规则,在考虑怎么优化数据库。

    建索引、删外键,分表分库,减少连表操作,多点冗余字段
    wedoub
        12
    wedoub  
       2019-04-11 16:06:47 +08:00 via iPhone
    大表拆分成小表,以空间换取时间
    luozic
        13
    luozic  
       2019-04-11 16:06:55 +08:00
    多不多? 多去牛逼的服器; 少,那就修代,改架,改查。
    14march
        14
    14march  
       2019-04-11 16:11:26 +08:00
    @yangxin0 暴躁程序员 我喜欢
    alamaya
        15
    alamaya  
       2019-04-11 16:14:05 +08:00
    才 1KW,我觉得 mysql 完全木问题呀
    qiyuey
        16
    qiyuey  
       2019-04-11 16:16:57 +08:00
    不要在数据库写 join,全部放到代码侧,这样对缓存和分库分表都比较友好。
    rb6221
        17
    rb6221  
       2019-04-11 16:18:10 +08:00
    超过 1000w 的表较多,就这一句话我觉得你们当初的架构就有问题
    要么在之前预测的时候就开始做分表
    要么优化业务和表结构,要知道多个 1000w 数量级的查询不是什么常见的场景。
    simapple
        18
    simapple  
       2019-04-11 16:19:40 +08:00
    看具体业务
    看具体瓶颈操作卡在哪里
    看优化预算

    所以没有一个固定的范式去解决


    也许预算是第一个要先搞清楚的
    loading
        19
    loading  
       2019-04-11 16:23:31 +08:00 via Android
    一次查几万?瓶颈可能会在磁盘 io 或者网络 io 上了。
    ginux
        20
    ginux  
    OP
       2019-04-11 16:24:31 +08:00
    @love 是的
    ginux
        21
    ginux  
    OP
       2019-04-11 16:25:28 +08:00
    @alamaya 性能问题很大,因为都是大表
    ginux
        22
    ginux  
    OP
       2019-04-11 16:34:29 +08:00
    @ggicci 索引、分库、分表都做了,例如经常会在表里面执行 count ()或者 in(几千个参数)操作,性能低
    9684xtpa
        23
    9684xtpa  
       2019-04-11 16:53:06 +08:00
    @ginux #22 count in?
    houshengzi
        24
    houshengzi  
       2019-04-11 17:46:50 +08:00
    我们也有这样的表,有七八个字段都是 0/1/2 这些值,但是业务需求基本上都用到这几个字段做条件

    对于这种优化也在头疼着。
    kiddult
        25
    kiddult  
       2019-04-11 17:48:42 +08:00
    @ginux 几千个参数。。。。。还是先拿板砖把开发拍死再说吧
    ducklyl
        26
    ducklyl  
       2019-04-11 18:09:16 +08:00
    千万级索引优化好,也还行。
    接着分表,拆成 N 张子表,再不行的话,再分库,分成多个库。
    opengps
        27
    opengps  
       2019-04-11 18:14:40 +08:00
    大表做运算真的很麻烦,这个方面没经验,只能提示下分表或者分段 sum 试下
    vmskipper
        28
    vmskipper  
       2019-04-11 18:42:46 +08:00
    推到重来 做个容量规划 重新设计
    Antihank
        29
    Antihank  
       2019-04-11 19:26:13 +08:00
    @qiyuey 大佬,我的习惯就是这样,但是问题是这样会很容易内存溢出,而且如果项目有 dubbo 或类似的 Service 层分布式架构,然后从各个服务去拉取数据,数据量变大,往往需要通过中间件来传递。。。到现在我都没有很好的解决办法。。。
    Raymon111111
        30
    Raymon111111  
       2019-04-11 20:21:59 +08:00
    查几万的数据单纯用一个表没有什么办法

    建议换存储引擎, 比如 ES
    tomczhen
        31
    tomczhen  
       2019-04-11 23:54:25 +08:00 via Android   3
    抛开一些低级错误,在 OLTP 数据库上做 OLAP 业务怎么优化都会难受。

    对于时效要求不高的分析就没必要每次都在数据库统计实时数据,定时执行保存结果就好。实效性要求高的高读写数据(热点)只能用缓存解决,业务代码需要处理一致性问题。

    还有就是一些需求本身不适合在关系数据库上做,可以利用 CDC 之类的把数据同步到其他类型数据库。
    redsonic
        32
    redsonic  
       2019-04-12 02:47:39 +08:00
    库表是防在 SSD 上面吗? 不是的话先迁移到 SSD 再说,如果不是频繁写表的话.
    jbiao520
        33
    jbiao520  
       2019-04-12 07:57:13 +08:00 via Android
    in 几千个参数是什么鬼
    0xABCD
        34
    0xABCD  
       2019-04-12 08:12:58 +08:00 via Android
    @ginux 看出来了,问题出在 SQL 写得太渣,架构再牛也没用
    leonme
        35
    leonme  
       2019-04-12 08:52:07 +08:00 via Android
    @tomczhen 看了一圈,这个回答比较靠谱,也是大厂通用的解决方式
    lsongiu
        36
    lsongiu  
       2019-04-12 09:01:50 +08:00
    tidb?
    daodao116
        37
    daodao116  
       2019-04-12 09:40:19 +08:00
    如果是事实性要求较高的需求
    1、索引(尽量保证 join 是索引字段,当然这些字段本身是否建索引还值得商榷)
    2、分区

    如果是统计形需求,就像楼上 @tomczhen 说的,定时统计好了,慢一点没事,单线程不会拖垮数据库。

    再复杂一点就是设计和代码层面的改动了,要看具体业务需求和表结构设计了,可能就不是一句两句能说清楚的了。
    HarryQu
        38
    HarryQu  
       2019-04-12 10:28:10 +08:00
    @tomczhen 实效性要求高的高读写数据(热点)只能用缓存解决,业务代码需要处理一致性问题。

    在这句话中, 缓存是在哪里做 ? 直接使用 Msql 数据库缓存,还是在业务层做缓存, 如 Redis。
    HarryQu
        39
    HarryQu  
       2019-04-12 10:34:30 +08:00
    @tomczhen
    在实时性要求高的情况下, 如果数据库数据频繁更新,是否意味着缓存时常 miss ? 这样的话缓存也不能起到很好的效果。
    那么如何处理时效性要求高且数据庞大且数据频繁更新的问题 ?
    90928yao
        40
    90928yao  
       2019-04-12 11:20:43 +08:00
    clickhouse 强烈推荐
    90928yao
        41
    90928yao  
       2019-04-12 11:21:27 +08:00
    没看题 太多关联 clickhouse 可能性能不太好
    whp1473
        42
    whp1473  
       2019-04-12 14:57:14 +08:00
    1.分表、分库。横向、纵向切分。
    纵向:将数据分为易变更、高热度数据和不易变更、低热度数据,把 N 列,切分成 M 个表,关联。降低单表的数据储量
    横向:可以考虑用数据库中间件 mycat 之类的,将原有的数据按照 ID 分片到不同库。查询时数据库中间件会自动聚合返回。但要考虑事务问题、使用 join 困难问题。
    2.数据异构
    mysql 数据库对于以 T 为单位的数据本身就存在瓶颈,可以考虑通过 binlog 或者消息的方式同步数据到其他存储引擎(例如:es、hbase),通过实时计算或定时计算将要查询、join 的数据的结果回流到 mysql、es,然后通过该存储进行查询。
    3.热点数据缓存
    对于敏感的数据,需要考虑缓存问题,可以使用 Redis+本地缓存+ZK 的方式做多级缓存。

    异构数据同步快慢,依赖于消息的消费速度,速度慢可以扩容 mq 机器、消费者机器,基本可以保障基本同步。
    whp1473
        43
    whp1473  
       2019-04-12 15:04:26 +08:00
    或者换 Oracle ?单表几亿数据应该没问题吧,写存储过程、优化 Sql、索引,应该能撑很长时间
    whp1473
        44
    whp1473  
       2019-04-12 15:07:24 +08:00
    一次性查几万数据,这个还好吧。一次实时取几万数据,那就只能打产品了。
    ggicci
        45
    ggicci  
       2019-04-12 15:56:59 +08:00
    @ginux 把这些你认为是瓶颈的查询往死里优化,实在优化到头了就得考虑其它可替代的解决方案了。你可以看看是否有其它数据库系统能更好地来处理你的瓶颈部分,想想把这部分数据外挂给这些系统处理能否解决你的需求。
    wind3110991
        46
    wind3110991  
       2019-04-12 16:33:09 +08:00
    ( 1 )订单信息、运营报表数据,建议分表分库,或者更换成 ES 搜索引擎;
    ( 2 )时序数据换成 Hbase、openTSDB ;
    ( 3 )建议检查优化索引,重建表然后瘦身、迁移;
    ( 4 )实时性不强的数据一定要加缓存;
    太多大表联表,说明你的业务逻辑需要优化了,尽量用空间换时间,把业务逻辑尽量放在代码端而不是 mysql,
    mysql 就是个最傻瓜的东西来用就对了,不要 XJB 用,尽量不要在大表间做 join ;
    Ja1
        47
    Ja1  
       2019-04-16 09:49:36 +08:00
    千万级别数据库优化,按照从简到繁:
    1.sql 语句以及索引优化
    2.加缓存
    3.主从复制,主主复制,读写分离
    4.分区
    5.垂直切分
    6.水平切分,(迫不得已才使用,会增加难度)
    lolizeppelin
        48
    lolizeppelin  
       2019-07-11 14:52:45 +08:00
    介绍你个东西 maxwell

    可以读取 mysql 的 binglog 以 json 形式发到卡夫卡 /redia/rabiitmq....
    这样你可以在不改业务代码的情况下,把数据转发到其他的位置做 olap 啦

    把要做分析的数据丢 pg 里比 mysql 里分析快多了...

    不过 maxwell 的代码好像有点简单..有资源可以考虑 debezium
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2511 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 15:33 PVG 23:33 LAX 08:33 JFK 11:33
    Do have faith in what you're doing.
    ubao 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