当前位置: 首页 > news >正文

16 “count(*)“ 和 “count(1)“ 和 “count(field1)“ 的差异

前言

经常会有面试题看到这样的问题 “ select count(*) ”, “ select count(field1) ”, “ select count(1) ” 的效率差异啥的

然后 我们这里 就来探索一下 这个问题

我们这里从比较复杂的 select count(field1) 开始看, 因为 较为复杂的处理过程 会留一下一些关键的调试的地点, 然后根据这些地点去参照看一下 其他的查询 在这些地点分别都是怎么做的?

 

 

“ select count(field1) ” 的实现

首先是语法解析这边, 将 field1 解析为一个 PTI_in_sum_expr 里面包含了 field1 的 token 和 location 等等 

0303b8a80115467189848a8849e37f77.png

 

然后就是后面将 PTI_in_sum_expr resolve 成为 Item_field, 当然 这里也仅仅是维护了 field1 的 token 的相关信息, 后面才会填充 table 等等信息 

bc893b0e88f24cb69fc8ed04cac85542.png

 

然后是根据上下文填充目标字段的 table 的信息, field 的信息 

537342954bc6422cabcd41d6fc4e73af.png

 

然后就是迭代符合条件的记录, 然后根据给定的字段是否为空的信息, 来判断是否统计计数 

80e999c8cf56423f9d3c742c440532e3.png

 

然后判断 是否为空的标准为, 字段值是否是 NULL 

对应的处理方式如下 

5c450f93492e47c5b893b96b16c1a0ff.png

 

 

“ select count(*) ” 的实现

首先是语法解析这边, 将 * 解析为 NULL, 这里上下文包含了 location 的相关信息

2370993fab754f268dcbab01d77baf17.png

 

sql 解析完成之后, args[0] 之前为 NULL, 被更新为了 “Item_int(0)”

b6c5d5dcd6b84e16b8f8639de8022f4f.png

 

然后 setup_fields 这边, 没有做 太多的事情, Item_int 这边的 fix_fields 这边是走的默认处理 Item::fix_fields

d3c0cbc85f554bcbbaaa03675de45d3f.png

 

Item::fix_fields 的处理如下, 仅仅是一个标记的更新 

ad2aa5e465274d5c9b8b850b19497f31.png

 

然后就是迭代符合条件的记录, 然后根据给定的字段是否为空的信息, 来判断是否统计计数 

60bf166d50a84834b63592278dcdacf5.png

 

判断是否为空的判断标注哪位, 恒不为空 

类似于一个基本数据类型的 int 值为 0, 恒不为 NULL

eae65e9f9b6a4f8593acb27cf25e1f44.png

 

 

“ select count(1) ” 的实现

首先是语法解析这边, 将 1 解析为 PTI_in_sum_expr 里面 PTI_num_literal_num 包含了长了常量 ”1”, 这里上下文包含了 location 的相关信息

68dc01aca8c84d92b0cb60b4e1942a5c.png

 

然后 setup_fields 这边, 没有做 太多的事情, Item_int 这边的 fix_fields 这边是走的默认处理 Item::fix_fields

3b8300ff1c6a4980b16e95495da32e51.png

 

然后就是迭代符合条件的记录, 然后根据给定的字段是否为空的信息, 来判断是否统计计数 

PTI_num_literal_num 这边判断为不为空的方式也是基于 Item::is_null, 也是恒不为空 

dc45b9884d904875b3bc01d1c69162ca.png

 

 

“ select count(“1“) ” 的实现

其他的我们就不去看了, 仅仅看一下 Item_sum_count::add 这边的上下文 

解析出来的 对象有所调整, 但是结果不变, PTI_text_literal_text_string 这边判断为不为空的方式也是基于 Item::is_null, 也是恒不为空 

0fb832d4f4fb49279f8d456f9d0017cc.png

 

 

“ select count(NULL) ” 的实现

其他的我们就不去看了, 仅仅看一下 Item_sum_count::add 这边的上下文 

解析出来的 对象有所调整, 但是结果不变, Item_null 这边判断为不为空的方式是基于 Item_null::is_null, 是恒为空 

因此 最终的查询结果为 0

85309490573347fba623e504312e7c87.png

 

然后 Item_null::is_null 的处理方式如下, 恒为空 

5e034727ea1a4f71bb04afd9d3d0e3dc.png

 

 

总结

大致可以分成两类, “ select count(field1) ” 和 ”其他select count” 

影响效率的差异主要在于 是否是全表扫描, 扫描的是聚簇索引还是非聚簇索引

假设是索引扫描, 则几者的差异并不大, 主要的差异在于 比较的时候前者复杂一点, 后者快一点, 但是扫描的记录数量有限, 效率影响不大 

假设是全表扫描, 主要的影响就是 “ select count(field1) ” 是走聚簇索引, 还是非聚簇索引了, 然后 “其他select count” 会优先选择较小的非聚簇索引, 造成的影响主要是 io 的开销, 走非聚簇索引所需要的 io 较小

 

 

完 

 

 

 

http://www.lryc.cn/news/160437.html

相关文章:

  • 【云原生进阶之PaaS中间件】第一章Redis-1.4过期策略
  • windows弹出交互式服务检测一键取消bat脚本
  • 接口使用的最佳时机
  • freertos之任务运行时间统计实验
  • Js中一些数组常用API总结
  • LlamaIndex:将个人数据添加到LLM
  • Mojo 摸脚语言,似乎已经可以安装
  • Spark 6:Spark SQL DataFrame
  • 区块链智能合约编程语言 Solidity
  • 将SSL证书设置成HTTPS的详细步骤
  • 43、Flink之Hive 读写及详细验证示例
  • 2023数模国赛C 题 蔬菜类商品的自动定价与补货决策-完整版创新多思路详解(含代码)
  • javaScript:DOM中常用尺寸
  • 决策树算法学习笔记
  • Verilog_mode常用的几个用法
  • MySQL之MHA高可用配置及故障切换
  • java实现状态模式
  • Selling a Menagerie(cf)
  • python-55-打包exe执行
  • linux并发服务器 —— IO多路复用(八)
  • 企微SCRM营销平台MarketGo-ChatGPT助力私域运营
  • linux C++ 海康截图Demo
  • MySQL的事务隔离级别
  • 企业大语言模型智能问答的底层基础数据知识库如何搭建?
  • 【腾讯云 Cloud Studio 实战训练营】使用python爬虫和数据可视化对比“泸州老窖和五粮液4年内股票变化”
  • Linux之Shell概述
  • 手写Spring:第2章-创建简单的Bean容器
  • 在Windows上通过SSH公私钥实现无密码登录Linux
  • 使用ppt和texlive生成eps图片(高清、可插入latex论文)
  • html5学习笔记19-SSE服务器发送事件(Server-Sent Events)