Skip to content

Commit

Permalink
update explain (#983)
Browse files Browse the repository at this point in the history
* update explain

* update explain

* update explain

* fix
  • Loading branch information
yangj1211 authored Mar 19, 2024
1 parent 4c717d5 commit 870978a
Show file tree
Hide file tree
Showing 9 changed files with 556 additions and 428 deletions.
19 changes: 10 additions & 9 deletions docs/MatrixOne/Performance-Tuning/explain/explain-aggregation.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ Hash Aggregation 算法在执行聚合时使用 Hash 表存储中间结果。此
1 row in set (0.01 sec)

mysql> EXPLAIN SELECT /*+ HASH_AGG() */ count(*) FROM t1;
+-------------------------------------------+
| QUERY PLAN |
+-------------------------------------------+
| Project |
| -> Aggregate |
| Aggregate Functions: starcount(1) |
| -> Table Scan on db1.t1 |
+-------------------------------------------+
4 rows in set (0.01 sec)
+-------------------------------------------------+
| QUERY PLAN |
+-------------------------------------------------+
| Project |
| -> Aggregate |
| Aggregate Functions: starcount(1) |
| -> Table Scan on db1.t1 |
| Aggregate Functions: starcount(1) |
+-------------------------------------------------+
5 rows in set (0.00 sec)
```
15 changes: 8 additions & 7 deletions docs/MatrixOne/Performance-Tuning/explain/explain-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,14 @@ EXPLAIN SELECT * FROM t WHERE a = 1;
**返回结果**

```sql
+------------------------------------------------+
| QUERY PLAN |
+------------------------------------------------+
| Project |
| -> Table Scan on aab.t |
| Filter Cond: (CAST(t.a AS BIGINT) = 1) |
+------------------------------------------------+
+--------------------------------+
| QUERY PLAN |
+--------------------------------+
| Project |
| -> Table Scan on db1.t |
| Filter Cond: (t.a = 1) |
+--------------------------------+
3 rows in set (0.01 sec)
```

`EXPLAIN` 实际不会执行查询。`EXPLAIN ANALYZE` 可用于实际执行查询并显示执行计划。如果 MatrixOne 所选的执行计划非最优,可用 `EXPLAIN``EXPLAIN ANALYZE` 来进行诊断。
Expand Down
34 changes: 16 additions & 18 deletions docs/MatrixOne/Performance-Tuning/explain/explain-subqueries.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,18 @@ MatrixOne 会执行多种子查询相关的优化,以提升子查询的执行
7 rows in set (0.02 sec)

> explain select * from t1 where t1.id in (select t2.id from t2 where t2.id>=3);
+---------------------------------------------------------------+
| QUERY PLAN |
+---------------------------------------------------------------+
| Project |
| -> Join |
| Join Type: SEMI |
| Join Cond: (t1.id = t2.id) |
| -> Table Scan on db1.t1 |
| -> Project |
| -> Table Scan on db1.t2 |
| Filter Cond: (CAST(t2.id AS BIGINT) >= 3) |
+---------------------------------------------------------------+
8 rows in set (0.00 sec)
+-----------------------------------------+
| QUERY PLAN |
+-----------------------------------------+
| Project |
| -> Join |
| Join Type: SEMI |
| Join Cond: (t1.id = t2.id) |
| -> Table Scan on db1.t1 |
| -> Table Scan on db1.t2 |
| Filter Cond: (t2.id >= 3) |
+-----------------------------------------+
7 rows in set (0.01 sec)
```

可以看到这个执行计划的执行顺序是:
Expand Down Expand Up @@ -116,13 +115,12 @@ mysql> explain SELECT * FROM t1 WHERE id in (SELECT id FROM t2 WHERE t1.ti = t2.
| Project |
| -> Join |
| Join Type: SEMI |
| Join Cond: (t1.ti = t2.ti), (t1.id = t2.id) |
| Join Cond: ((t1.ti = t2.ti) IS TRUE), (t1.id = t2.id) |
| -> Table Scan on db1.t1 |
| -> Project |
| -> Table Scan on db1.t2 |
| Filter Cond: (CAST(t2.id AS BIGINT) >= 4) |
| -> Table Scan on db1.t2 |
| Filter Cond: (t2.id >= 4) |
+---------------------------------------------------------------+
8 rows in set (0.01 sec)
7 rows in set (0.00 sec)
```

MatrixOne 在处理该 SQL 语句时会将其改写为等价的 `JOIN` 查询:`select t1.* from t1 join t2 on t1.id=t2.id where t2.id>=4;`,可以看到这个执行计划的执行顺序是:
Expand Down
37 changes: 17 additions & 20 deletions docs/MatrixOne/Performance-Tuning/explain/explain-views.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,15 @@
如上述示例所示,新建了一个命名为 *v1* 的 VIEW,并查询 *v1* 的结果。那么我们看一下这个视图的执行过程:

```sql
> explain select * from v1;
+--------------------------------------------------------------+
| QUERY PLAN |
+--------------------------------------------------------------+
| Project |
| -> Project |
| -> Project |
| -> Table Scan on db1.t1 |
| Filter Cond: (CAST(t1.id AS BIGINT) > 4) |
+--------------------------------------------------------------+
5 rows in set (0.00 sec)
> explain select * from v1;
+----------------------------------+
| QUERY PLAN |
+----------------------------------+
| Project |
| -> Table Scan on db1.t1 |
| Filter Cond: (t1.id > 4) |
+----------------------------------+
3 rows in set (0.01 sec)
```

可以看到 Project 为这次查询过程中的执行顺序的父节点,首先是从缩进最多的子节点开始计算,完成后“流入”它的上层父节点,最终“流入”Project 父节点。
Expand All @@ -75,13 +73,12 @@

```sql
> explain select * from (select * from t1) sub where id > 4;
+--------------------------------------------------------+
| QUERY PLAN |
+--------------------------------------------------------+
| Project |
| -> Project |
| -> Table Scan on db1.t1 |
| Filter Cond: (CAST(t1.id AS BIGINT) > 4) |
+--------------------------------------------------------+
4 rows in set (0.03 sec)
+----------------------------------+
| QUERY PLAN |
+----------------------------------+
| Project |
| -> Table Scan on db1.t1 |
| Filter Cond: (t1.id > 4) |
+----------------------------------+
3 rows in set (0.00 sec)
```
48 changes: 24 additions & 24 deletions docs/MatrixOne/Performance-Tuning/explain/explain-walkthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@ SQL 是一种声明性语言,因此无法通过 SQL 语句直接判断一条
1 row in set (0.00 sec)

> explain select count(*) from a where a>=2 and a<=8;
+-----------------------------------------------------------------------------------+
| QUERY PLAN |
+-----------------------------------------------------------------------------------+
| Project |
| -> Aggregate |
| Aggregate Functions: starcount(1) |
| -> Table Scan on aab.a |
| Filter Cond: (CAST(a.a AS BIGINT) >= 2), (CAST(a.a AS BIGINT) <= 8) |
+-----------------------------------------------------------------------------------+
5 rows in set (0.00 sec)
+---------------------------------------------------+
| QUERY PLAN |
+---------------------------------------------------+
| Project |
| -> Aggregate |
| Aggregate Functions: starcount(1) |
| -> Table Scan on db1.a |
| Filter Cond: (a.a >= 2), (a.a <= 8) |
+---------------------------------------------------+
5 rows in set (0.01 sec)
```

以上是该查询的执行计划结果。从 `Filter Cond` 算子开始向上看,查询的执行过程如下:

1. 先执行过滤条件 `Filter Cond`即过滤出数据类型为 `BIGINT` 且大于等于 2,小于等于 8 的整数,按照计算推理,应该为 `(2),(3),(4),(5),(6),(7),(8)`
2. 扫描数据库 aab 中的表 a。
1. 先执行过滤条件 `Filter Cond`即过滤出数据字段为 `a` 且大于等于 2,小于等于 8 的整数,按照计算推理,应该为 `(2),(3),(4),(5),(6),(7),(8)`
2. 扫描数据库 db1 中的表 a。
3. 聚合计算满足条件整数的个数,为 7 个。

最终,得到查询结果为 7,即 `count(*)` = 7。
Expand All @@ -55,18 +55,18 @@ EXPLAIN ANALYZE 是一个用于查询的分析工具,它将向你显示 SQL

```sql
> explain analyze select count(*) from a where a>=2 and a<=8;
+-------------------------------------------------------------------------------------------------------------------------------+
| QUERY PLAN |
+-------------------------------------------------------------------------------------------------------------------------------+
| Project |
| Analyze: timeConsumed=0us inputRows=1 outputRows=1 inputSize=8bytes outputSize=8bytes memorySize=8bytes |
| -> Aggregate |
| Analyze: timeConsumed=3317us inputRows=2 outputRows=2 inputSize=8bytes outputSize=16bytes memorySize=16bytes |
| Aggregate Functions: starcount(1) |
| -> Table Scan on aab.a |
| Analyze: timeConsumed=6643us inputRows=31 outputRows=24 inputSize=96bytes outputSize=64bytes memorySize=64bytes |
| Filter Cond: (CAST(a.a AS BIGINT) >= 2), (CAST(a.a AS BIGINT) <= 8) |
+-------------------------------------------------------------------------------------------------------------------------------+
+---------------------------------------------------------------------------------------------------------------------------------------+
| QUERY PLAN |
+---------------------------------------------------------------------------------------------------------------------------------------+
| Project |
| Analyze: timeConsumed=0ms waitTime=0ms inputRows=1 outputRows=1 InputSize=8bytes OutputSize=8bytes MemorySize=8bytes |
| -> Aggregate |
| Analyze: timeConsumed=0ms waitTime=0ms inputRows=7 outputRows=1 InputSize=28bytes OutputSize=8bytes MemorySize=16bytes |
| Aggregate Functions: starcount(1) |
| -> Table Scan on db1.a |
| Analyze: timeConsumed=0ms waitTime=0ms inputRows=8 outputRows=7 InputSize=32bytes OutputSize=28bytes MemorySize=75bytes |
| Filter Cond: (a.a >= 2), (a.a <= 8) |
+---------------------------------------------------------------------------------------------------------------------------------------+
8 rows in set (0.00 sec)
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ mysql> EXPLAIN VERBOSE SELECT * FROM t1 WHERE (col1 = 1 AND col3 = 7369) OR (col
+-----------------------------------------------------------------------------------------------------+
| QUERY PLAN |
+-----------------------------------------------------------------------------------------------------+
| Project (cost=1000.00 outcnt=1000.00 selectivity=1.0000) |
| Project (cost=1000.00 outcnt=1000.00 selectivity=1.0000 blockNum=1) |
| Output: t1.col1, t1.col2, t1.col3 |
| -> Table Scan on db2.t1 (cost=1000.00 outcnt=1000.00 selectivity=1.0000 blockNum=1) |
| -> Table Scan on db1.t1 (cost=1000.00 outcnt=1000.00 selectivity=1.0000 blockNum=1) |
| Output: t1.col1, t1.col2, t1.col3 |
| Table: 't1' (0:'col1', 1:'col2', 2:'col3') |
| Hit Partition: p0, p2 |
Expand All @@ -79,16 +79,15 @@ CREATE TABLE t1 (
) PARTITION BY KEY(col3) PARTITIONS 4;

mysql> EXPLAIN SELECT * FROM t1 WHERE col3 = 7990 OR col3 = 7988;
+-------------------------------------------------------------------+
| QUERY PLAN |
+-------------------------------------------------------------------+
| Project |
| -> Table Scan on db1.t1 |
| Hit Partition: p0, p1 |
| Filter Cond: ((t1.col3 = 7990) or (t1.col3 = 7988)) |
| Block Filter Cond: ((t1.col3 = 7990) or (t1.col3 = 7988)) |
+-------------------------------------------------------------------+
5 rows in set (0.00 sec)
+-------------------------------------------------------------+
| QUERY PLAN |
+-------------------------------------------------------------+
| Project |
| -> Table Scan on db1.t1 |
| Hit Partition: p0, p1 |
| Filter Cond: ((t1.col3 = 7990) or (t1.col3 = 7988)) |
+-------------------------------------------------------------+
4 rows in set (0.01 sec)
```

在这个 SQL 中,条件 `col3 = 7990` 可以确定所有结果都位于分区 p0 上。条件 `col3 = 7988` 可以确定所有结果都位于分区 p1 上。由于这两个条件的关系是 OR,因此只需要扫描 p0 和 p1 两个分区,分区裁剪的结果是 p0 和 p1。
Expand All @@ -101,16 +100,15 @@ Key 分区由于内部使用哈希算法造成的无序性,不适用于连续

```sql
mysql> EXPLAIN SELECT * FROM t1 WHERE col3 >= 7782;
+----------------------------------------------+
| QUERY PLAN |
+----------------------------------------------+
| Project |
| -> Table Scan on db1.t1 |
| Hit Partition: all partitions |
| Filter Cond: (t1.col3 >= 7782) |
| Block Filter Cond: (t1.col3 >= 7782) |
+----------------------------------------------+
5 rows in set (0.00 sec)
+----------------------------------------+
| QUERY PLAN |
+----------------------------------------+
| Project |
| -> Table Scan on db1.t1 |
| Hit Partition: all partitions |
| Filter Cond: (t1.col3 >= 7782) |
+----------------------------------------+
4 rows in set (0.00 sec)
```

#### 场景二
Expand All @@ -119,25 +117,22 @@ mysql> EXPLAIN SELECT * FROM t1 WHERE col3 >= 7782;

```sql
mysql> EXPLAIN SELECT * FROM t1 WHERE col3 = (SELECT col3 FROM t2 WHERE t1.col3 = t2.col3 AND t2.col1 < 5);
+------------------------------------------------------+
| QUERY PLAN |
+------------------------------------------------------+
| Project |
| -> Filter |
| Filter Cond: (t1.col3 = t2.col3

) |
| -> Join |
| Join Type: SINGLE |
| Join Cond: (t1.col3 = t2.col3) |
| -> Table Scan on db1.t1 |
| Hit Partition: all partitions |
| -> Table Scan on db1.t2 |
| Hit Partition: all partitions |
| Filter Cond: (t2.col1 < 5) |
| Block Filter Cond: (t2.col1 < 5) |
+------------------------------------------------------+
12 rows in set (0.00 sec)
+---------------------------------------------------+
| QUERY PLAN |
+---------------------------------------------------+
| Project |
| -> Filter |
| Filter Cond: (t1.col3 = t2.col3) |
| -> Join |
| Join Type: SINGLE |
| Join Cond: (t1.col3 = t2.col3) |
| -> Table Scan on db1.t1 |
| Hit Partition: all partitions |
| -> Table Scan on db1.t2 |
| Hit Partition: all partitions |
| Filter Cond: (t2.col1 < 5) |
+---------------------------------------------------+
11 rows in set (0.00 sec)
```

这个查询每读取一行数据,都会从子查询中获取结果并构建等值过滤条件 `col3 = ?`。然而,分区裁剪只在查询计划生成阶段生效,而不是执行阶段,因此无法进行分区裁剪。
Expand Down
Loading

0 comments on commit 870978a

Please sign in to comment.