Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • MySQL

    • 基础部分

      • 初识MySQL
      • 基础架构&日志
      • 事务隔离
      • 全局锁、表锁、行锁
      • 事务的隔离性和行锁
      • 索引
      • 索引深入(中)
      • 内存脏页刷盘
      • 数据库表的空间回收
      • count
        • 1.count(*)实现方式
        • 2.不同count的用法
          • 2.1count(主键id)
          • 2.2count(1)
          • 2.3count(字段)
          • 2.4count(*)
          • 2.5总结
      • order by
      • SQL语句性能差异分析
      • 幻读与间隙锁
      • 加锁规则案例分析
      • binlog和redolog如何写入磁盘
      • MySQL一致性与高可用性
      • kill命令
      • 全表扫描与内存占用
      • join
      • 临时表与内存表
      • 自增主键
      • insert操作加锁场景分析
      • grant
      • 分区表
      • 思维导图
    • 实战与处理方案

    • 面试

  • ORM框架

  • 数据库
  • MySQL
  • 基础部分
phan
2023-06-22
目录

count

# count

MyISAM:将表的行数存储在磁盘中,查询时直接取,速度快。

InnoDB:MVCC机制导致不同行记录对于不同事务的可见性都是不同的,因此InnoDB只能将一行一行读出来进行判断和计数,效率低。

InnoDB扫描表时会进行相应的优化,会选择普通索引树下的记录进行扫描,而不会选择主键索引树,因为相较之下主键索引叶子节点的数据量要大于普通索引,这样可以减少扫描的数据量。

# 1.count(*)实现方式

逻辑一致:插入数据后,表记录行数count和select读取到的记录是相互匹配的。不能出现行数增加了,但是这条数据查不到;或者是这条插入的记录可以被读取到,但是表记录数没有更新。

  • Redis存放count(*)表的行数

存在问题:插入数据时,redis更新行数与数据库插入记录这两个操作不具有原子性,因此如果在redis更新和数据库表更新之间有并发读操作,那么得到的结果就会出现逻辑不一致。

  • 将count(*)行数存入数据库中的一张单独的表

利用MySQL事务的特性,当前事务只有同时完成insert插入记录,以及表行数加一这两个操作后才提交事务,从而使插入操作和加一操作其它事务都可见。保证了两个操作的一致性。

💡考虑性能的话,先插入数据,再update更新计数表。因为在并发场景下,更新操作冲突时会加行锁,而计数表冲突的概率比行记录冲突的概率更高,因此把更新操作放在最后,可以减少更新表行记录锁的持有时间,从而最大程度减少锁等待。

# 2.不同count的用法

InnoDB引擎返回数据给server层时,遵循以下原则:server层要什么就给什么,并且InnoDB只会给必要的数据

# 2.1count(主键id)

  • InnoDB引擎将每行的id都取出来,返回给server层
  • server层判断如果不为空,则按行累加

# 2.2count(1)

  • InnoDB引擎直接放回每行记录给server层(相比于count(主键)更快,因为少了解析取出id值这个过程)
  • server层将“1”放进每一行数据,不为空则累加

# 2.3count(字段)

  • InnoDB取出每行该字段的值给server层
  • 无论该字段定义为null或者时not null。计算时只有字段的值非null才会进行累加。

# 2.4count(*)

InnoDB对count(*)进行了优化,不需要把全部字段取出来一个个判断是否为空,直接记录行数。

# 2.5总结

性能效率上,count(*)≈count(1)>count(id)>count(字段)

编辑 (opens new window)
#数据库
上次更新: 2023/12/15, 15:49:57
数据库表的空间回收
order by

← 数据库表的空间回收 order by→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式