V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
rqxiao
V2EX  ›  MySQL

mysql 单表 5 千万的数据量 , count(*) 耗时很长有办法优化吗

  •  
  •   rqxiao · 215 天前 · 3393 次点击
    这是一个创建于 215 天前的主题,其中的信息可能已经有所发展或是发生改变。
    单表 5 千万 现在 count(*) 要 17s 左右
    36 条回复    2022-09-09 15:24:48 +08:00
    chengyiqun
        1
    chengyiqun  
       215 天前
    看你带条件了没, 条件是否走上索引了.
    MoYi123
        2
    MoYi123  
       215 天前
    据我所知 pg 是没有的, mysql 应该也没有.
    KouShuiYu
        3
    KouShuiYu  
       215 天前
    换成 count(1) 然后加上索引
    pannanxu
        4
    pannanxu  
       215 天前
    据说这样子可以

    explain select id from project

    或者如果数据量准确度不需要太高,可以直接把查出来的数量丢进缓存
    qq8331199
        5
    qq8331199  
       215 天前
    直接是没有办法的,就是慢
    要么 redis 缓存这个 count ,先 count 一次,后面有增删,就去更新这个 count
    keepeye
        6
    keepeye  
       215 天前
    正在显示第 0 - 24 行 (共 31392729 行, 查询花费 13.9842 秒。)
    SELECT count(*) FROM `orders`

    rds 8 核 16g 高可用实例
    sivacohan
        7
    sivacohan  
       215 天前
    select TABLE_ROWS from information_schema.TABLES where TABLE_SCHEMA = 'db' AND TABLE_NAME='tbl';

    不要求准确性的话,可以这么查询。
    keepeye
        8
    keepeye  
       215 天前
    不求精确的话,并且能查询 mysql 库的话,可以读取 innodb_table_stats
    westoy
        9
    westoy  
       215 天前
    缓存啊

    不过我感觉你可能表设计有问题或者硬盘 IO 被拖爆了? 再怎么慢,5000 万数据 17S 也有点离谱啊.......
    bootvue
        10
    bootvue  
       215 天前
    这个数据量是时候考虑考虑 es clickhouse 这些了
    rqxiao
        11
    rqxiao  
    OP
       215 天前
    有 where 条件的,而且还比较多

    SELECT COUNT(1) FROM tb_task
    <where>
    AND is_deleted = 0
    AND data_type != 1
    <if test="fileType != null and fileType != ''"> AND file_type = #{fileType}</if>
    <if test="fileSource != null"> AND file_source = #{fileSource}</if>
    <if test="auditStatus != null"> AND review_status = #{auditStatus}</if>
    <if test="auditStatus != null"> AND analysis_status = 2</if>
    zibber
        12
    zibber  
       215 天前
    clickhouse
    MoYi123
        13
    MoYi123  
       215 天前
    建议直接说服产品, 分页改成一页页翻, 用上一页的主键去查下一页, 然后行数大于 10000 行直接显示 10000+. 基本只能这么做.
    tairan2006
        14
    tairan2006  
       215 天前
    改成下拉分页,别算总数了。
    dwlovelife
        15
    dwlovelife  
       215 天前
    用 mysql 一句话 无解, 要么改需求, 要么上别的数据库
    CEBBCAT
        16
    CEBBCAT  
       215 天前
    @KouShuiYu #3 真佩服,能一下子猜到楼主是附带了 WHERE 的计数👍
    makelove
        17
    makelove  
       215 天前
    先想明白你要的是什么,而不是怎么实现
    5 千万级保证实现精确,这 tm 什么需求,造火箭都不需要这么高精度
    djoiwhud
        18
    djoiwhud  
       215 天前 via Android
    条件未命中索引,或者是结果集超比例,触发了全表扫描。

    优化办法,优化 sql ,优化索引。如果是结果集超大,导致索引查询转全表扫描,需要考虑需求调整。或者是技术方案调整。

    做数据冗余,规避汇总语句,也是可以的。
    djoiwhud
        19
    djoiwhud  
       215 天前 via Android
    不带条件的 sql ,别说五千万,就是一个亿,count *也可以快速查询出来。
    这个问题换 count 1 没任何影响。
    honamx
        20
    honamx  
       215 天前
    建组合索引试试,is_deleted, data_type, fileType, fileSource ,auditStatus
    redorblacck886
        21
    redorblacck886  
       215 天前
    mysql 数据达到瓶颈了 、再怎么优化还是性能差的。考虑做数据切分 分表之类的。
    chendl111
        22
    chendl111  
       215 天前 via Android
    换 lykasm
    bthulu
        23
    bthulu  
       215 天前
    触发器啊, 新增一条满足查询条件的数据就记录+1, 删除一条就记-1. 后面只查这个记录数就行了, 1 毫秒都用不到就能精确返回
    justanetizen
        24
    justanetizen  
       215 天前
    加个表或者缓存里存储该表的总数据数
    pengtdyd
        25
    pengtdyd  
       215 天前
    这不是技术的问题,这是产品的问题。
    justanetizen
        26
    justanetizen  
       215 天前
    还有一个办法,用 insert 、delete 触发器
    yousabuk
        27
    yousabuk  
       215 天前 via iPhone
    换 myisam
    taogen
        29
    taogen  
       215 天前
    表结构、索引和 explain 贴一下啊
    akira
        30
    akira  
       215 天前
    产品问题,改成查最近一段时间的 数据,例如 30 天,7 天, 然后这样就可以走索引了。
    hubahuba
        31
    hubahuba  
       214 天前
    这这这不分表
    iseki
        32
    iseki  
       214 天前 via Android
    才 5000 万分啥表
    KouShuiYu
        33
    KouShuiYu  
       213 天前
    检查下 where 条件是不是有类型转换之类的操作,之前有张表
    conv_time :: date between :dateStart and :dateEnd
    修改成了 conv_time between :dateStart and (date :dateEnd + interval '1 day' - interval '1 second')
    查询时间直接从 3s 干到了 20ms
    CrazyMonkeyV
        34
    CrazyMonkeyV  
       212 天前
    我们也遇到了这个问题,在特定需求下,近乎无解。
    NoahVI
        35
    NoahVI  
       201 天前
    @qq8331199 那还是用 binlog 好点。
    NoahVI
        36
    NoahVI  
       201 天前
    还是考虑用 es 吧
    关于   ·   帮助文档   ·   博客   ·   nftychat   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   1772 人在线   最高记录 5556   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 16:54 · PVG 00:54 · LAX 09:54 · JFK 12:54
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.