深入理解select count(*)底层究竟做了什么
正如我们假如用剧本/措施来举办逐行的扫表操纵,实现上就会涉及下面 2 个 SQL:
详细涉及到此例的代码,SQL 层到存储引擎层的挪用相关,读取阶段的挪用栈如下:(供参考) 我们可以看到,无论是哪一个分支的读取,最终都殊途同归于 row_search_mvcc函数。 以上是对 LOOP 中的代码做一些扼要的声名,下面来看 row_search_mvcc与 evaluate_join_record 怎样输出最终的 count 功效。 2.3 行可见性及 row_search_mvcc 函数 这里我们首要通过一组 case 和几个题目来看行可见性对 COUNT( * ) 的影响。 Q:对付SELECT COUNT( * ) FROM t可能SELECT MIN(id) FROM t操纵,第一次的读行操纵读到的是表 t 中 ( B+ 树最左叶节点 page 内 ) 的最小记录吗?( ha_index_first 为何也挪用 row_search_mvcc 来获取最小 key 值?) A:不必然。纵然是MIN ( id ) 也不必然就读取的是 id 最小的那一行,由于也同样有行可见性的题目,现实上 index_read 取到的是 当前事宜内语句可见的最小 index 记录。这也反应了前面提到的 join_read_first 与 join_read_next “殊途同归”到 row_search_mvcc 是理所该当的。 Q:针对图中最后一问,假如事宜 X 是 RU ( Read-Uncommitted ) 断绝级别,且 C-Insert ( 100 ) 的完成是在 X-count( * )执行进程中 ( 仅扫描到 5 或 10 这笔记录 ) 完成的,那么 X-count( * ) 在事宜 C-Insert ( 100 ) 完成后,可否在之后的读取进程中看到 100 这笔记录呢? A:MySQL 采纳”读到什么就是什么”的计策,即X-count( * )在后头可以读到 100 这笔记录。 2.4 evaluate_join_record 与列是否为空 Q:某一行怎样计入 count? A:两种环境会将所读的行计入 count: 1、假如 COUNT 函数中的参数是某列,则会判定所读行中该列界说是否 Nullable以及该列的值是否为 NULL;若两者均为是,则不管帐入 count,不然将计入 count。
2、假如 COUNT 中带有 * ,则会判定这部门的整行是否为 NULL,假如判定参数为 NULL,则忽略该行,不然 count++。
Q: 出格地,对付 SELECT COUNT(id) FROM t,个中 id 字段是表 t 的主键,则怎样? A:结果上等价于 COUNT( * )。由于无论是 COUNT( * ),照旧 COUNT ( pk_col ) 都是由于有主键从而充实断定索取数据不为 NULL,这类 COUNT 表达式可以用于获取当前可见的表行数。 Q: 用户层面临 InnoDB COUNT( * ) 的优化操纵题目 A:这个题目是业界认识的一个题目,扫描非空独一键可获得表行数,但所涉及的字节数也许会少许多(在表的行长与主键、独一键的长度相差较多时),相对的 IO 价钱小许多。 相干挪用栈参考如下: 二、数据布局: Q:count 值存储在哪个内存变量里? A:SQL 理会后,存储于表达 COUNT( * ) 这一项中,((Item_sum_count*)item_sum)->count 如下图所示回首我们之前“COUNT( * )前置流程”部门提到的 JOIN 布局。 即 SQL 理会器为每个 SQL 语句举办布局化,将其放在一个 JOIN 工具 ( join ) 中来表达。在该工具中建设并添补了一个列表 result_field_list 用于存放功效列,列表中每个元素则是一个功效列的 ( Item_result_field*) 工具 ( 指针 ) 。 在 COUNT( * )-case 中,功效列列表只包括一个元素,( Item_sum_count: public Item_result_field ) 范例工具 ( name = “COUNT( * )”),个中该类所特有的成员变量 count即为所求。 三、MyISAM 全表 COUNT( * ) 因为 MyISAM引擎并不常用于现实营业中,仅做扼要描写如下:
四、几个题目 (编辑:湖南网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |