14 | count(*)这么慢,我该怎么办?

一、count(*) 的实现方式

不同引擎,不同实现方式。InnoDB,事务支持、并发能力、安全优于 MyISAM

MyISAM 总行存磁盘,直接返回,效率高;加where 不能返回这么快

InnoDB :一行行从引擎读出,然后累积

二、为什么 InnoDB 把数字存起来?

多版本并发控制(MVCC)原因,InnoDB 不确定“返回多少行”。表 t  10000 条记录,三用户并行会话

A 启动事务,查询表总行

B 启动事务,插入一行,查询表总行;

C 启动单独语句,插入一行,查询表总行。

上到下按照时间顺序执行,同一行语句是在同一时刻执行

图 1 会话 A、B、C 的执行流程  

InnoDB默认可重复读。对于 count(*) InnoDB 一行行地读出判断,可见行用于计算总行数

如对 MVCC 记忆模糊,回顾《事务隔离:为什么你改了我还看不见?》和第 8 篇文章《事务到底是隔离的还是不隔离的?》

InnoDB 索引组织表,主键索引树叶子节点是数据普通索引树叶子节点是主键值普通比主键索引树。 count(*)遍历哪个结果都一样。MySQL 优化器找最小遍历

show table status 结果里面也有一个 TABLE_ROWS 用于显示这个表当前有多少行,这个命令执行挺快的,误差 40% 到 50%。显示的行数也不能直接使用。

1)MyISAM count(*) 快,不支持事务

2)show table status 快,不准确;

3)InnoDB  count(*) 遍历全表,准确,性能问题

三、自己计数方法,优缺点

场景:显示交易系统操作总数。思路:找地方操作记录行数

3.1用缓存系统保存计数

更新频繁库,插入Redis 加 1,删减 1。读和更新都快。

可能会丢失。异常重启,计数操作丢失,到库里执行 count(*) 获取 。异常重启不经常可接受

显示操作总数最近操作100 条记录。先到 Redis ,再到数据表里取数据记录。不精确:

1.  100 行结果最新,Redis 计数没加 1

2.  另一种是,100 行没最新,Redis 计数加1

图 2 会话 A、B 执行时序图

插入 R,加 1; B 就查询页面显示时需要的数据。不一致。

先写数据表,再改 Redis 计数。读的时候是先读 Redis,再读数据表,顺序相反的。顺序一样的话,是不是就没问题了?换一下,再看结果。

图 3 调整顺序后,会话 A、B 的执行时序图

反过来,会话 B 在 T3 时刻查询的时,Redis加 1 ,查不到新插入行

3.2 数据库保存计数

计数放到数据库表 C ,用“事务”解决

图 4 会话 A、B 的执行时序图

B 读仍在 T3 执行,更新还没提交,加 1对B 不可见,一致。

四、不同count 用法

count() 聚合函数,返回结果集,一行行判断,参数不是 NULL,累计值加 1。

count(*)、count(主键 id) 和 count(1) 

性能差别原则:

1.  server 要什么就给什么

2.  InnoDB 只给必要值

3.  优化器只优化 count(*) 语义为“取行数”,其他“显而易见”的优化并没有做。

1)count(主键 id):遍历整表,每行id 值都取出,返回给 server 层。判断非空,按行累加。

2)count(1) :遍历整表,不取值。server 层每行放“1”,判断非空,按行累加。

        比 count(主键 id) 快。不涉及到解析数据行,拷贝字。

3)count(字段):第一条原则,server 层要什么,InnoDB 就返回什么。

1.  “字段”not null,一行行读,判断非null,按行累加;

2.  允许为 null,值取判断,不是 null 累加。

4)count(*) 是例外,不取值,肯定不是 null,按行累加。

效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),尽量使用 count(*)

小结

获表行数两种方法:不同引擎count(*) 方式不一样,缓存存储计数值问题。

计数放在 Redis 里面,两个不同的存储构成的系统,不支持分布式事务,无法拿到一致视图。计数值也放MySQL 中,解决一致性视图问题。

InnoDB 支持事务,用好事务原子性和隔离性简化开发逻辑

思考题

刚刚方案中,用事务确保计数准确。中间结果不被读到,因此修改计数值插入新记录的顺序不影响结果。并发系统性能考虑,这个事务,先插入,还是先更新计数表?

更新涉及行锁竞争,先插入减少锁等待。计数表热点行,加锁时间要足够短

一个事务,两个语句:insert into 数据表;update 计数表,加 1。知识点在《行锁功过:怎么减少行锁对性能的影响?》

计数表记录多个业务表行数,表名字段加唯一索引

CREATE TABLE  `rows_stat` (

  `table_name` varchar(64) NOT NULL,

  `row_count` int(10) unsigned NOT NULL,

  PRIMARY KEY (`table_name`)

) ENGINE=InnoDB;

更新时传 where table_name=$table_name,主键索引,更新加行锁只会锁在一行上。

业务表插入数据,计数表更新不同行,不会有行锁

评论1

字段上有索引,且非空,count(字段)效率还最差

count(id)也可用普通索引

评论2

库里总共 30w 数据 。 第一次用 count(*) 是 120多ms , 第二次就是 60多 ms 。 第三次用了 count(1) ,也是60多ms 。 请问 count(*) 这两次的前后时间差是什么原因,也会走缓存 ?

进了Buffer pool

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容