COUNT 算子用于兼容 Oracle 的 ROWNUM 功能,实现 ROWNUM 表达式的自增操作。

在一般场景下,当 SQL 查询含有 ROWNUM 时,SQL 优化器就会在生成执行计划的时候分配一个 COUNT 算子。当然在一些情况下,SQL 优化器会将含有 ROWNUM 的 SQL 改写为 LIMIT 算子,这时就不会再分配 COUNT 算子。

正常分配 COUNT 算子的场景

示例 1:含有 ROWNUM 的 SQL 查询正常分配 COUNT 算子场景。

obclient>CREATE TABLE t1(c1 INT, c2 INT);
Query OK, 0 rows affected (0.12 sec)

obclient>INSERT INTO t1 VALUES(1, 1);
Query OK, 1 rows affected (0.12 sec)

obclient>INSERT INTO t1 VALUES(3, 3);
Query OK, 1 rows affected (0.12 sec)

obclient>INSERT INTO t1 VALUES(5, 5);
Query OK, 1 rows affected (0.12 sec)

Q1: 
obclient>EXPLAIN SELECT c1,ROWNUM FROM t1G;
*************************** 1. row ***************************
Query Plan:
| ====================================
|ID|OPERATOR   |NAME|EST. ROWS|COST|
------------------------------------
|0 |COUNT      |    |1        |37  |
|1 | TABLE SCAN|T1  |1        |36  |
====================================

Outputs & filters: 
-------------------------------------
  0 - output([T1.C1], [rownum()]), filter(nil)
  1 - output([T1.C1]), filter(nil), 
      access([T1.C1]), partitions(p0)

obclient>SELECT c1,ROWNUM FROM t1;
+------+--------+
| C1   | ROWNUM |
+------+--------+
|    1 |      1 |
|    3 |      2 |
|    5 |      3 |
+------+--------+
3 rows in set (0.01 sec)

上述示例中,执行计划展示中的 outputs & filters 详细展示了 COUNT 算子的输出信息如下:

信息名称

含义

output

该算子输出的表达式。

其中 rownum() 表示 ROWNUM 对应的表达式。

filter

该算子上的过滤条件。

由于示例中 COUNT 算子没有设置 filter,所以为 nil。

从上述执行计划示例的输出结果可以发现,ROWNUM 对应的表达式的初始值为 1,每通过一次 COUNT 算子,COUNT 算子就会为 ROWNUM 对应的表达式的值加上 1,实现 ROWNUM 表达式的自增操作。

不分配 COUNT 算子的场景

示例 2:含有 rownum 的 SQL 改写为 LIMIT 后,不分配 COUNT 算子的场景。

Q2:
obclient>EXPLAIN SELECT 1 FROM DUAL WHERE ROWNUM < 2G;
*************************** 1. row ***************************
Query Plan:
| ====================================
|ID|OPERATOR   |NAME|EST. ROWS|COST|
------------------------------------
|0 |LIMIT      |    |1        |1   |
|1 | EXPRESSION|    |1        |1   |
====================================

Outputs & filters: 
-------------------------------------
  0 - output([1]), filter(nil), limit(?), offset(nil)
  1 - output([1]), filter(nil)
      values({1})

从上述执行计划示例的输出结果可以发现,虽然 SQL 中含有 ROWNUM,但是经过 SQL 优化器改写之后,已经将涉及含有 ROWNUM 的表达式转换为了等价的 LIMIT 表达式,转换的好处在于可以做更多的优化,详细信息请参见 LIMIT

冒牌SEO

前端开发者,欢迎大家一起沟通和交流。

Share
Published by
冒牌SEO

Recent Posts

聊聊vue3中的defineProps

在Vue 3中,defineP…

1 周 ago

在 Chrome 中删除、允许和管理 Cookie

您可以选择删除现有 Cooki…

2 周 ago

自定义指令:聊聊vue中的自定义指令应用法则

今天我们来聊聊vue中的自定义…

3 周 ago

聊聊Vue中@click.stop和@click.prevent

一起来学下聊聊Vue中@cli…

4 周 ago

Nginx 基本操作:启动、停止、重启命令。

我们来学习Nginx基础操作:…

1 月 ago

Vue3:手动清理keep-alive组件缓存的方法

Vue3中手动清理keep-a…

1 月 ago