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

MySQL 单表三千万条数据,怎么优化 count 查询?

  •  
  •   CodeXx · 2020-09-29 10:38:41 +08:00 · 6060 次点击
    这是一个创建于 1543 天前的主题,其中的信息可能已经有所发展或是发生改变。

    innodb,20 来个字段,每天有几十万条数据插入,在不做分表的情况下,怎么优化查询?现在是 count 查询很慢,5s 左右,带上查询条件比如近一个月就更慢了 10 多 s

    46 条回复    2020-09-30 10:47:06 +08:00
    Joyboo
        1
    Joyboo  
       2020-09-29 10:54:31 +08:00
    分区,索引
    lidashuang
        2
    lidashuang  
       2020-09-29 10:55:29 +08:00
    可以不做 count,就不做
    非做的话,看看能不能自己统计

    或者放 es 里?
    CodeXx
        3
    CodeXx  
    OP
       2020-09-29 11:05:15 +08:00
    @Joyboo 索引对 count 查询貌似没用,还是得扫描全表
    CodeXx
        4
    CodeXx  
    OP
       2020-09-29 11:05:47 +08:00
    @lidashuang 分页查询用到的,也不知道会用什么条件查询
    huntcool001
        5
    huntcool001  
       2020-09-29 11:13:03 +08:00   ❤️ 2
    每天晚上把到零点的数据库的数据,离线做分析统计,count+各种查询条件等等(大概 es 或者其他框架,我不是很清楚), 结果存起来.

    然后每天的数据,你有了当天零点以来的 binlog,就有了增量的 count. 和离线分析做出来的 count 结合起来.

    大概是这个思路. 大厂都是这么干的.
    RickyC
        6
    RickyC  
       2020-09-29 11:17:10 +08:00
    如果数据库不经常改变
    根据查询条件建立几个 count 表, 里面保存根据各种条件得到的 count 数字;
    并给 count 表建立索引

    这样也许行
    RickyC
        7
    RickyC  
       2020-09-29 11:19:34 +08:00
    接上
    如果你每天还有 10w 的数据更改, 可以在每次更改的时候修改 count 表.

    我觉得用 count 表可能解决你的问题. 预先统计
    egglin
        8
    egglin  
       2020-09-29 11:24:42 +08:00
    异构吧,es + mysql
    maigebaoer
        9
    maigebaoer  
       2020-09-29 11:31:40 +08:00 via Android
    如果直接 count,用 count(*)吧,没啥特别好的建议。要不就直接入库前统计,写 count 字段。
    mrhhsg
        10
    mrhhsg  
       2020-09-29 11:33:21 +08:00
    三千万的 count 那还不是一瞬间的事?加内存就完了
    v2orz
        11
    v2orz  
       2020-09-29 11:35:28 +08:00
    插入的时候维护 count 信息?同 9L
    Leigg
        12
    Leigg  
       2020-09-29 11:44:35 +08:00 via Android   ❤️ 1
    不要做实时查询即可,延迟个 30s 几分钟,数量到达一定高度后,多数场景中的实时统计就变成了一种伪需求,如果一定需要,换数据库,比如 clickhouse
    RangerWolf
        13
    RangerWolf  
       2020-09-29 11:46:37 +08:00
    12 楼+1,clickhouse 的统计非常🐂
    dongisking
        14
    dongisking  
       2020-09-29 11:47:39 +08:00
    这问题我这边也遇到过,特别是做管理后台特别多复杂的条件做 where 的 count 根本无法缓存,最后的解决办法是把 count 缓存,然后页面显示“大约 xx 条”,每一段时间更新一次
    cccy0
        15
    cccy0  
       2020-09-29 11:55:01 +08:00
    近实时统计的话建议放 es
    sagaxu
        16
    sagaxu  
       2020-09-29 12:00:25 +08:00 via Android
    @CodeXx 索引 count 时有没有用,要看区分度,你索引类似性别这种低区分度的当然没用
    liuzhaowei55
        17
    liuzhaowei55  
       2020-09-29 12:05:13 +08:00 via Android
    不要使用 count,如果是 id 自增而且没有删除数据可以使用最后一条数据的 id,或者使用 explain 返回的 rows,这个值不太准但响应很快
    nomansky
        18
    nomansky  
       2020-09-29 12:29:18 +08:00
    加个表,里面保存 count,每插入一条数据更新 count
    haohappy
        19
    haohappy  
       2020-09-29 12:55:12 +08:00
    count 慢 select 不慢吗
    dzdh
        20
    dzdh  
       2020-09-29 12:58:18 +08:00
    @CodeXx 分页场景的话,where 排序字段 >上一页的最大值 limt x, n
    juntao
        21
    juntao  
       2020-09-29 13:10:53 +08:00
    最近有遇到,多字段 WHERE 查询,1kw 条不到,不想分表
    1 做好索引。可以用 EXPLAIN 来帮助优化。 -- 有一定效果
    2 限制查询的时间范围 -- 特别有效
    3 异构,mysql,redis 、elasticsearch 等等单独统计数据, 因为 2 能够满足我们的需求,所以没采用。


    @liuzhaowei55 直接获取自增 id 也是一种方法诶。之前没考虑,需要匹配场景。
    fuyufjh
        22
    fuyufjh  
       2020-09-29 13:12:19 +08:00
    mysql 8.0 有 parallel query,能大幅提升这个场景
    zakokun
        23
    zakokun  
       2020-09-29 13:13:58 +08:00
    1. 索引对 count 有用
    2. 几千万的表 count 需求来自哪里?为何要每天 count
    3. 维护一个 count 表,插入数据的时候更新 count 表
    4. ES
    hooopo
        24
    hooopo  
       2020-09-29 13:17:26 +08:00 via Android
    j747677392
        25
    j747677392  
       2020-09-29 13:51:42 +08:00
    如果都是日志型的数据(用于分析,没删改的话) 可以用 hdfs+imapla,支持 sql,几亿数据查询毫秒吧
    wangyzj
        26
    wangyzj  
       2020-09-29 14:02:04 +08:00
    count 和索引没关系
    es 是个选项
    或者单独做个统计信息表
    或者用 redis 来分页
    CodeXx
        27
    CodeXx  
    OP
       2020-09-29 14:18:20 +08:00
    @RickyC
    @maigebaoer
    @v2orz
    @Leigg
    @RangerWolf
    这样只能存总的 count 吧,查询有其他条件的更慢,14 楼这种差不多
    CodeXx
        28
    CodeXx  
    OP
       2020-09-29 14:19:31 +08:00
    @haohappy select 很快
    cokolin
        29
    cokolin  
       2020-09-29 14:29:22 +08:00
    能否首先描述一下为何要 count,例如页面查询需要总量,还是什么需要
    cokolin
        30
    cokolin  
       2020-09-29 14:33:45 +08:00
    还有查询用到的字段是否是固定的,如果的固定的话,是否可以增加索引,看看 EXPLAIN 分析用到的索引是否正确
    另外也可以用一些业务的方式避免分页查询总量的
    xsm1890
        31
    xsm1890  
       2020-09-29 14:42:26 +08:00
    myisam 自动维护总数,count 的过程不用计算只需要度数即可
    raysmond
        32
    raysmond  
       2020-09-29 14:45:16 +08:00
    如果只是 count,且对实时性要求那么高(能接受 10s ?),有个很简单的做法能大幅提高速度
    用一个线程异步 count 就好,用的地方直接从内存取,对使用方来说超级快
    fangcan
        33
    fangcan  
       2020-09-29 14:49:17 +08:00
    不要求精确的话 用 explain
    Evilk
        34
    Evilk  
       2020-09-29 15:20:39 +08:00
    如果是分页用的 count,如果数据量太大,我一般给个模糊值
    每隔段时间,更新一次,即可
    liwl
        35
    liwl  
       2020-09-29 15:21:35 +08:00
    是想弄图表吧 每天 count
    rickiey
        36
    rickiey  
       2020-09-29 16:27:40 +08:00
    mongoDB shared cluster 不行吗? 我没用过
    lshero
        37
    lshero  
       2020-09-29 16:29:48 +08:00
    OLAP 的功能交给别的数据库做吧
    mofeishiwo
        38
    mofeishiwo  
       2020-09-29 16:32:34 +08:00
    megatron7
        39
    megatron7  
       2020-09-29 17:06:00 +08:00
    没有数据断层吧并且有自增主键索引可以用:
    select max(id) from table;
    bbao
        40
    bbao  
       2020-09-29 17:07:23 +08:00
    @CodeXx mysql 是行锁,是否全表需要看你后面 where 条件。
    ragnaroks
        41
    ragnaroks  
       2020-09-29 17:10:07 +08:00
    做个同步的从库,统计类需求从从库查,不影响主库业务
    vus520
        42
    vus520  
       2020-09-29 17:11:57 +08:00
    1,能不 count 就不 count
    2,Mysql 有触发器,能不能插入的时候写到其它某个 value 上
    3,缓存神器你值得拥有
    liyunlong41
        43
    liyunlong41  
       2020-09-29 17:18:03 +08:00 via iPhone
    加索引应该也要扫描索引树吧。
    插入的时候更新 count,似乎会影响插入效率。
    将数据同步到其他数据库例如 es 或者从库,查询从这些里面查好像不错。
    定时任务周期性的计算 count 也可以,查询时直接用结果,也是有一定的时延。
    everhythm
        44
    everhythm  
       2020-09-29 18:25:34 +08:00 via iPhone
    1.索引 or 各种缩小量级的方法对 count 有效,所以最近一个月的 count 你可以优化


    2.来吧业务查询中间件,把 query 拆分为若干 subquery,再分发到不同实例,最后汇总,但是到这一步已经快超出 rds 范畴了,查询速度还不能接受的话考虑其他方式
    lidashuang
        45
    lidashuang  
       2020-09-29 20:59:42 +08:00
    @CodeXx 分页查询用 我之前都是去掉 count😄
    xuewuchen
        46
    xuewuchen  
       2020-09-30 10:47:06 +08:00
    索引吧。。。LAST ID
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2314 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:18 · PVG 09:18 · LAX 17:18 · JFK 20:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.