Mysql count(*)、count(1)、count(主键)、count(普通字段) 性能对比

发布时间 2023-12-12 17:28:43作者: 变体精灵

count(*): 底层会转化为 count(0) 来处理,默认横向扫描聚集索引树,如果有二级索引就扫描二级索引树(因为二级索引树更小,扫描成本低),扫描到一行记录之后,将该记录返回给 Server 层,由于参数是 0,不为 NULL,所以不需要读取记录中的任何字段,直接将 count 变量加 1

count(1): 处理方式和 count(0) 类似

count(主键 id): 默认横向扫描聚集索引树,如果有二级索引就扫描二级索引树(因为二级索引树更小,扫描成本低),扫描到一行记录之后,将该记录返回给 Server 层,然后 Server 层读取该记录的主键 id 值,判断主键 id 值是否为 NULL,如果不为 NULL,就将 count 变量加 1

count(普通字段): 不会扫描任何索引树,只能全表扫描,然后将该记录返回给 Server 层,然后 Server 层读取该记录的字段值,判断字段值是否为 NULL,如果不为 NULL,就将 count 变量加 1

 

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

  • 如果没有二级索引的情况下就会横向扫描主键索引
  • 如果存在二级索引的情况下,不会扫描主键索引,转而扫描二级索引(因为二级索引一般情况下,相比于主键索引来说,其占用存储空间更小,性能更高)

count(*) 和 count(1) 的底层处理逻辑类似,性能是相同的

count(主键 id) 扫描到记录之后还会去判断主键 id 是否为 NULL,多了一个读取主键 id 和判断的过程,性能略低于 count(*)

count(普通字段) 只能走全表扫描的方式,不能扫描索引树

只有主键索引的情况下: count(*) = count(0) = count(1) > count(主键 id) > count(普通字段)

有主键索引和二级索引的情况下: count(*) = count(0) = count(1) > count(主键 id) = count(普通字段)