国产集中式数据库SQL评测 — 逻辑优化

原创
数据库 其他数据库
谓词重写,又称为等价谓词重写,是指将原执行效率低的谓词改写为效率高的谓词并重写SQL,从而提高SQL的整体执行效率的一种优化手段。其本质是在于不同谓词的处理效率存在差异所导致。

数据库的逻辑优化,是查询优化过程中的关键阶段,旨在通过调整查询语句的逻辑结构和操作顺序,生成更高效的执行计划,而不涉及底层存储结构或硬件资源。其核心在于利用关系代数的等价变换和查询重写技术,减少计算量和中间结果规模。

1. 逻辑优化—谓词重写

谓词重写,又称为等价谓词重写,是指将原执行效率低的谓词改写为效率高的谓词并重写SQL,从而提高SQL的整体执行效率的一种优化手段。其本质是在于不同谓词的处理效率存在差异所导致。常见的谓词重写规则如下

1).优化规则

1.png1.png

2).数据库支持情况

2.png2.png

3).数据库测评

-- Oracle-- Like(未改写)SQL> select * from emp where emp_name like 'emp12%';--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   118 |  3304 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   118 |  3304 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("EMP_NAME" LIKE 'emp12%')
-- Between And(改写)SQL> select * from emp where salary between 1000 and 1200;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |  1799 | 50372 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |  1799 | 50372 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("SALARY"<=1200 AND "SALARY">=1000)   -- IN-OR/IN-ANY(改写)SQL> select * from emp where dept_id in (20,30);--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   189 |  5292 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   189 |  5292 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=20 OR "DEPT_ID"=30)   -- OR-ANY(未改写)SQL> select * from emp where dept_id=20 or dept_id=30;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   189 |  5292 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   189 |  5292 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=20 OR "DEPT_ID"=30)   --ALL/ANY-MIN/MAX(改写)SQL> SELECT * FROM emp WHERE salary > ANY (  SELECT salary FROM emp WHERE dept_id=20);----------------------------------------------------------------------------| Id  | Operation           | Name | Rows  | Bytes | Cost (%CPU)| Time     |----------------------------------------------------------------------------|   0 | SELECT STATEMENT    |      |  8999 |   325K|    32   (7)| 00:00:01 ||   1 |  MERGE JOIN SEMI    |      |  8999 |   325K|    32   (7)| 00:00:01 ||   2 |   SORT JOIN         |      | 10000 |   273K|    16   (7)| 00:00:01 ||   3 |    TABLE ACCESS FULL| EMP  | 10000 |   273K|    15   (0)| 00:00:01 ||*  4 |   SORT UNIQUE       |      |   101 |   909 |    16   (7)| 00:00:01 ||*  5 |    TABLE ACCESS FULL| EMP  |   101 |   909 |    15   (0)| 00:00:01 |----------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   4 - access(INTERNAL_FUNCTION("SALARY")>INTERNAL_FUNCTION("SALARY"))       filter(INTERNAL_FUNCTION("SALARY")>INTERNAL_FUNCTION("SALARY"))   5 - filter("DEPT_ID"=20)-- NOT(改写)SQL> select * from emp where not dept_id!=20;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   101 |  2828 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   101 |  2828 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=20)-- OR-UNION(未改写)SQL> select * from emp where dept_id=1 or dept_id=2;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   141 |  3948 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   141 |  3948 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=1 OR "DEPT_ID"=2)   -- DM-- Like(改写)SQL> explain select * from emp where emp_name like 'emp12%';1   #NSET2: [1, 111, 163]2     #PRJT2: [1, 111, 163]; exp_num(6), is_atom(FALSE)3       #BLKUP2: [1, 111, 163]; IDX_EMP_NAME(EMP)4         #SSEK2: [1, 111, 163]; scan_type(ASC), IDX_EMP_NAME(EMP), scan_range['emp12','emp13'), is_global(0)
-- Between And(改写)SQL> explain select * from emp where salary between 1000 and 1200;1   #NSET2: [1, 1762, 163]2     #PRJT2: [1, 1762, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 1762, 163]; (EMP.SALARY >= var1 AND EMP.SALARY <= var2) SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)   -- IN-OR/IN-ANY(不改写)SQL> explain select * from emp where dept_id in (20,30);1   #NSET2: [3, 500, 193]2     #PRJT2: [3, 500, 193]; exp_num(6), is_atom(FALSE)3       #HASH2 INNER JOIN: [3, 500, 193];  KEY_NUM(1); KEY(DMTEMPVIEW_889193477.colname=EMP.DEPT_ID) KEY_NULL_EQU(0)4         #CONST VALUE LIST: [1, 2, 30]; row_num(2), col_num(1)5         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP); btr_scan(1)   -- OR-ANY(未改写)SQL> explain select * from emp where dept_id=20 or dept_id=30;1   #NSET2: [3, 500, 193]2     #PRJT2: [3, 500, 193]; exp_num(6), is_atom(FALSE)3       #HASH2 INNER JOIN: [3, 500, 193];  KEY_NUM(1); KEY(DMTEMPVIEW_889193481.colname=EMP.DEPT_ID) KEY_NULL_EQU(0)4         #CONST VALUE LIST: [1, 2, 30]; row_num(2), col_num(1)5         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP); btr_scan(1)   --ALL/ANY-MIN/MAX(未改写)SQL> explain SELECT * FROM emp WHERE salary > ANY (  SELECT salary FROM emp WHERE dept_id=20);1   #NSET2: [5, 500, 60]2     #PRJT2: [5, 500, 60]; exp_num(6), is_atom(FALSE)3       #HASH RIGHT SEMI JOIN32: [5, 500, 60]; op any;, key_num(0) join condition(EMP.SALARY > DMTEMPVIEW_889193482.colname)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP); btr_scan(1)5         #PRJT2: [1, 250, 60]; exp_num(1), is_atom(FALSE)6           #SLCT2: [1, 250, 60]; EMP.DEPT_ID = var17             #CSCN2: [1, 10000, 60]; INDEX33555484(EMP); btr_scan(1)
-- NOT(改写)SQL> explain select * from emp where not dept_id!=20;1   #NSET2: [1, 250, 163]2     #PRJT2: [1, 250, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 250, 163]; EMP.DEPT_ID = var1 SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)
-- OR-UNION(未改写)SQL> explain select * from emp where dept_id=1 or dept_id=2;1   #NSET2: [3, 500, 193]2     #PRJT2: [3, 500, 193]; exp_num(6), is_atom(FALSE)3       #HASH2 INNER JOIN: [3, 500, 193];  KEY_NUM(1); KEY(DMTEMPVIEW_889193490.colname=EMP.DEPT_ID) KEY_NULL_EQU(0)4         #CONST VALUE LIST: [1, 2, 30]; row_num(2), col_num(1)5         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP); btr_scan(1)   -- MySQL
-- Like(未改写)mysql> explain select * from emp where emp_name like 'emp12%';+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------+| id | select_type | table | partitions | type  | possible_keys | key          | key_len | ref  | rows | filtered | Extra                 |+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------+|  1 | SIMPLE      | emp   | NULL       | range | idx_emp_name  | idx_emp_name | 33      | NULL |  111 |   100.00 | Using index condition |+----+-------------+-------+------------+-------+---------------+--------------+---------+------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`emp_name` like 'emp12%') |+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- Between And(未改写)mysql> explain select * from emp where salary between 1000 and 1200;+----+-------------+-------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+| id | select_type | table | partitions | type  | possible_keys  | key            | key_len | ref  | rows | filtered | Extra                 |+----+-------------+-------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+|  1 | SIMPLE      | emp   | NULL       | range | idx_emp_salary | idx_emp_salary | 5       | NULL | 1328 |   100.00 | Using index condition |+----+-------------+-------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message                                                                                                                                                                                                                                                                                       |+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`salary` between 1000 and 1200) |+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- IN-OR/IN-ANY(未改写)mysql> explain select * from emp where dept_id in (20,30);+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    20.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message                                                                                                                                       |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` in (20,30)) |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- OR-ANY(未改写)mysql> explain select * from emp where dept_id=20 or dept_id=30;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    19.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where ((`testdb`.`emp`.`dept_id` = 20) or (`testdb`.`emp`.`dept_id` = 30)) |+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
--ALL/ANY-MIN/MAX(改写)mysql> explain SELECT * FROM emp WHERE salary > ANY (  SELECT salary FROM emp WHERE dept_id=20);+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | PRIMARY     | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    66.67 | Using where ||  2 | SUBQUERY    | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    10.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+2 rows in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where <nop>((`testdb`.`emp`.`salary` > (/* select#2 */ select min(`testdb`.`emp`.`salary`) from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` = 20)))) |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- NOT(改写)mysql> explain select * from emp where not dept_id!=20;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    10.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message                                                                                                                                 |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` = 20) |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- OR-UNION(未改写)mysql> explain select * from emp where dept_id=1 or dept_id=2;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    19.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where ((`testdb`.`emp`.`dept_id` = 1) or (`testdb`.`emp`.`dept_id` = 2)) |+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- Kingbase
-- Like(未改写)TEST=# explain select * from emp where emp_name like 'emp12%';                               QUERY PLAN------------------------------------------------------------------------ Gather  (cost=1000.00..16394.33 rows=100 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..15384.33 rows=42 width=42)         Filter: ((emp_name)::text ~~ 'emp12%'::text)         -- Between And (改写)TEST=# explain select * from emp where salary between 1000 and 1200;                                             QUERY PLAN----------------------------------------------------------------------------------------------------- Bitmap Heap Scan on emp  (cost=4857.22..17791.45 rows=183882 width=42)   Recheck Cond: ((salary >= '1000'::double precision) AND (salary <= '1200'::double precision))   ->  Bitmap Index Scan on idx_emp_salary  (cost=0.00..4811.24 rows=183882 width=0)         Index Cond: ((salary >= '1000'::double precision) AND (salary <= '1200'::double precision))         -- IN-OR/IN-ANY(改写为ANY)TEST=# explain select * from emp where dept_id in (20,30);                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..18284.33 rows=19000 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..15384.33 rows=7917 width=42)         Filter: (dept_id = ANY ('{20,30}'::numeric[]))
-- OR-ANY(未改写)TEST=# explain select * from emp where dept_id=20 or dept_id=30;                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..19317.00 rows=18910 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..16426.00 rows=7879 width=42)         Filter: ((dept_id = '20'::numeric) OR (dept_id = '30'::numeric))          -- ALL/ANY-MIN/MAX(未改写)TEST=# explain SELECT * FROM emp WHERE salary > ANY (  SELECT salary FROM emp WHERE dept_id=20);                                            QUERY PLAN-------------------------------------------------------------------------------------------------- Gather  (cost=1000.42..1009054.30 rows=333333 width=42)   Workers Planned: 2   ->  Nested Loop Semi Join  (cost=0.42..974721.00 rows=138889 width=42)         ->  Parallel Seq Scan on emp  (cost=0.00..14342.67 rows=416667 width=42)         ->  Index Scan using idx_emp_salary on emp emp_1  (cost=0.42..6667.14 rows=3156 width=8)               Index Cond: (salary < emp.salary)               Filter: (dept_id = '20'::numeric)               -- NOT(改写)               TEST=# explain select * from emp where not dept_id!=20;                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..17331.03 rows=9467 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..15384.33 rows=3945 width=42)         Filter: (dept_id = '20'::numeric)         -- OR-UNION(未改写)TEST=# explain select * from emp where dept_id=1 or dept_id=2;                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..18889.70 rows=14637 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..16426.00 rows=6099 width=42)         Filter: ((dept_id = '1'::numeric) OR (dept_id = '2'::numeric))             -- YashanDB-- Like(未改写)SQL> explain select * from emp where emp_name like 'emp12%';+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||  1 |  TABLE ACCESS BY INDEX ROWID   | EMP                  | TESTUSER   |       118|        1( 0)|                                ||* 2 |   INDEX RANGE SCAN             | IDX_EMP_NAME         | TESTUSER   |        60|        1( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   2 - Predicate : access("EMP"."EMP_NAME" LIKE 'emp12%')                   filter("EMP"."EMP_NAME" LIKE 'emp12%')
-- Between And(改写)SQL> explain select * from emp where salary between 1000 and 1200;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||  1 |  TABLE ACCESS BY INDEX ROWID   | EMP                  | TESTUSER   |       880|        6( 0)|                                ||* 2 |   INDEX RANGE SCAN             | IDX_EMP_SALARY       | TESTUSER   |       880|        2( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   2 - Predicate : access("EMP"."SALARY" >= 1000 AND "EMP"."SALARY"  <= 1200)   -- IN-OR/IN-ANY(不改写)SQL> explain select * from emp where dept_id in (20,30);+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |       200|       46( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" IN [20, 30])   -- OR-ANY(未改写)SQL> explain select * from emp where dept_id=20 or dept_id=30;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |       152|       47( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 20 OR "EMP"."DEPT_ID" = 30)   --ALL/ANY-MIN/MAX(改写)SQL> explain SELECT * FROM emp WHERE salary > ANY (  SELECT salary FROM emp WHERE dept_id=20);+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||  1 |  SUBQUERY                      | QUERY[1]             |            |          |             |                                ||  2 |   AGGREGATE                    |                      |            |         1|        1( 0)|                                ||  3 |    FIRST ROW                   |                      |            |         1|        1( 0)|                                ||* 4 |     TABLE ACCESS BY INDEX ROWID| EMP                  | TESTUSER   |         1|        1( 0)|                                ||  5 |      INDEX FULL SCAN (MIN/MAX) | IDX_EMP_SALARY       | TESTUSER   |         1|        1( 0)|                                ||* 6 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |      3301|       47( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Subquery NDV info - NDV percentage: 0.000000, NDV Expression: ()   4 - Predicate : filter("EMP"."DEPT_ID" = 20)   6 - Predicate : filter("EMP"."SALARY" > QUERY[1])   -- NOT(改写)SQL> explain select * from emp where not dept_id!=20;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |       103|       46( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 20)   -- OR-UNION(不改写)SQL> explain select * from emp where dept_id=1 or dept_id=2;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |       151|       47( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 1 OR "EMP"."DEPT_ID" = 2)
-- Vastbase
-- Like(未改写)vastbase=> explain select * from emp where emp_name like 'emp12%';                      QUERY PLAN------------------------------------------------------ Seq Scan on emp  (cost=0.00..243.00 rows=1 width=44)   Filter: ((emp_name)::text ~~ 'emp12%'::text)         -- Between And (改写)vastbase=> explain select * from emp where salary between 1000 and 1200;                                           QUERY PLAN------------------------------------------------------------------------------------------------- Bitmap Heap Scan on emp  (cost=50.84..196.05 rows=1814 width=44)   Recheck Cond: ((salary >= 1000::double precision) AND (salary <= 1200::double precision))   ->  Bitmap Index Scan on idx_emp_salary  (cost=0.00..50.39 rows=1814 width=0)         Index Cond: ((salary >= 1000::double precision) AND (salary <= 1200::double precision))                  -- IN-OR/IN-ANY(改写为ANY)vastbase=> explain select * from emp where dept_id in (20,30);                       QUERY PLAN-------------------------------------------------------- Seq Scan on emp  (cost=0.00..243.00 rows=204 width=44)   Filter: (dept_id = ANY ('{20,30}'::number[]))
-- OR-ANY(未改写)vastbase=> explain select * from emp where dept_id=20 or dept_id=30;                          QUERY PLAN-------------------------------------------------------------- Seq Scan on emp  (cost=0.00..268.00 rows=203 width=44)   Filter: ((dept_id = 20::number) OR (dept_id = 30::number))          -- ALL/ANY-MIN/MAX(未改写)vastbase=> explain SELECT * FROM emp WHERE salary > ANY (  SELECT salary FROM emp WHERE dept_id=20);                            QUERY PLAN------------------------------------------------------------------ Nested Loop Semi Join  (cost=0.00..9677.06 rows=3333 width=44)   Join Filter: (testuser.emp.salary > testuser.emp.salary)   ->  Seq Scan on emp  (cost=0.00..218.00 rows=10000 width=44)   ->  Materialize  (cost=0.00..243.46 rows=91 width=8)         ->  Seq Scan on emp  (cost=0.00..243.00 rows=91 width=8)               Filter: (dept_id = 20::number)               -- NOT(改写)               vastbase=> explain select * from emp where not dept_id!=20;                      QUERY PLAN------------------------------------------------------- Seq Scan on emp  (cost=0.00..243.00 rows=91 width=44)   Filter: (dept_id = 20::number)         -- OR-UNION(未改写)vastbase=> explain select * from emp where dept_id=1 or dept_id=2;                         QUERY PLAN------------------------------------------------------------ Seq Scan on emp  (cost=0.00..268.00 rows=196 width=44)   Filter: ((dept_id = 1::number) OR (dept_id = 2::number))

2. 逻辑优化—条件化简

条件化简,是指将语句中的条件子句部分优化,选择执行代价更小或更容易利用到索引、约束等的情况。从形式上看,条件子句可能由一元操作符、二元操作符、多元操作符组成。对于一元操作符而言,如果是相等运算,则比其他运算更易利用索引,且元组更少(选择率低的可能性更大);如果是范围运算,则应尽可能利用索引;如果能利用约束,则可以简化一些表达式,如非空约束有助于在条件表达式中判断对应列所在的表达式的值;如果表达式可以求值,则先求值有利于整个条件子句的计算。条件子句优化的本质是:尽早推知运算的结果以有利于对元组数进行计算,使得根据代价估算模型(元组数是重要的计算依据)可以准确地推演出最优查询执行计划。

1).优化规则

3.png3.png

2).数据库支持情况

4.png4.png

3).数据库测评

-- Oracle-- Having 并入 Where(不支持)SQL> SELECT * FROM emp where dept_id=100 HAVING salary > 5000;SELECT * FROM emp where dept_id=100 HAVING salary > 5000                                           *ERROR at line 1:ORA-00979: not a GROUP BY expression--去除冗余括号SQL> SELECT * FROM emp WHERE ((dept_id=2));--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   102 |  2856 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   102 |  2856 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=2)   -- 常量传递(支持)SQL> select * from emp where dept_id=10 and emp_id=dept_id;--------------------------------------------------------------------------------------| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------------------|   0 | SELECT STATEMENT            |        |     1 |    28 |     2   (0)| 00:00:01 ||*  1 |  TABLE ACCESS BY INDEX ROWID| EMP    |     1 |    28 |     2   (0)| 00:00:01 ||*  2 |   INDEX UNIQUE SCAN         | EMP_PK |     1 |       |     1   (0)| 00:00:01 |--------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=10)   2 - access("EMP_ID"=10)   -- 消除死码(支持)SQL> select * from emp where (0>1) or dept_id=10;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |    98 |  2744 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |    98 |  2744 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=10)   -- 表达式计算(支持)SQL> select * from emp where dept_id=1+2;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   107 |  2996 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   107 |  2996 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"=3)   -- 等式变换(不支持)SQL> select * from emp where -dept_id=-10;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |   100 |  2800 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |   100 |  2800 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter((-"DEPT_ID")=(-10))   -- 不等式转换(支持)SQL> select * from emp where salary >1100 and salary>2000;----------------------------------------------------------------------------------------------| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |----------------------------------------------------------------------------------------------|   0 | SELECT STATEMENT            |                |     1 |    28 |     4   (0)| 00:00:01 ||   1 |  TABLE ACCESS BY INDEX ROWID| EMP            |     1 |    28 |     4   (0)| 00:00:01 ||*  2 |   INDEX RANGE SCAN          | IDX_EMP_SALARY |     1 |       |     2   (0)| 00:00:01 |----------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   2 - access("SALARY">2000)   --谓词传递闭包(支持)SQL> select * from emp where emp_id>dept_id and dept_id>900;----------------------------------------------------------------------------------------------| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |----------------------------------------------------------------------------------------------|   0 | SELECT STATEMENT            |                |     1 |    28 |     3   (0)| 00:00:01 ||*  1 |  TABLE ACCESS BY INDEX ROWID| EMP            |     1 |    28 |     3   (0)| 00:00:01 ||*  2 |   INDEX RANGE SCAN          | IDX_EMP_DEPTID |     1 |       |     2   (0)| 00:00:01 |----------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("EMP_ID">900 AND "EMP_ID">"DEPT_ID")   2 - access("DEPT_ID">900)   -- 等价合取范式(支持)SQL> select * from emp where (0>1) and dept_id=10;---------------------------------------------------------------------------| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |---------------------------------------------------------------------------|   0 | SELECT STATEMENT   |      |     1 |    28 |     0   (0)|          ||*  1 |  FILTER            |      |       |       |            |          ||*  2 |   TABLE ACCESS FULL| EMP  |    98 |  2744 |    15   (0)| 00:00:01 |---------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter(NULL IS NOT NULL)   2 - filter("DEPT_ID"=10)   -- AND 操作符交换(不支持)SQL> select * from emp where dept_id+emp_id=1000 and salary>900;--------------------------------------------------------------------------| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |--------------------------------------------------------------------------|   0 | SELECT STATEMENT  |      |    90 |  2520 |    15   (0)| 00:00:01 ||*  1 |  TABLE ACCESS FULL| EMP  |    90 |  2520 |    15   (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------   1 - filter("DEPT_ID"+"EMP_ID"=1000 AND "SALARY">900)   -- DM-- Having 并入 Where(不支持)SQL> explain  SELECT * FROM emp where dept_id=100 HAVING salary > 5000;explain  SELECT * FROM emp where dept_id=100 HAVING salary > 5000;[-4028]:Error in line: 1Invalid having item.
--去除冗余括号(支持)SQL> explain SELECT * FROM emp WHERE ((dept_id=2));1   #NSET2: [1, 250, 163]2     #PRJT2: [1, 250, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 250, 163]; EMP.DEPT_ID = var1 SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)   -- 常量传递(不支持)SQL> explain select * from emp where dept_id=10 and emp_id=dept_id;1   #NSET2: [1, 1, 163]2     #PRJT2: [1, 1, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 1, 163]; EMP.DEPT_ID = var14         #BLKUP2: [1, 1, 163]; INDEX33555485(EMP)5           #SSEK2: [1, 1, 163]; scan_type(ASC), INDEX33555485(EMP), scan_range[exp_cast(10),exp_cast(10)], is_global(0)   -- 消除死码(支持)SQL> explain select * from emp where (0>1) or dept_id=10;1   #NSET2: [1, 250, 163]2     #PRJT2: [1, 250, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 250, 163]; EMP.DEPT_ID = var1 SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)   -- 表达式计算(支持)SQL> explain select * from emp where dept_id=1+2;1   #NSET2: [1, 250, 163]2     #PRJT2: [1, 250, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 250, 163]; EMP.DEPT_ID = var2 SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)   -- 等式变换(不支持)SQL> explain select * from emp where -dept_id=-10;1   #NSET2: [1, 250, 163]2     #PRJT2: [1, 250, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 250, 163]; -EMP.DEPT_ID = var2 SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)   -- 不等式转换(支持)SQL> explain select * from emp where salary >1100 and salary>2000;1   #NSET2: [1, 1, 163]2     #PRJT2: [1, 1, 163]; exp_num(6), is_atom(FALSE)3       #BLKUP2: [1, 1, 163]; IDX_EMP_SALARY(EMP)4         #SSEK2: [1, 1, 163]; scan_type(ASC), IDX_EMP_SALARY(EMP), scan_range(exp_cast(2000),max], is_global(0)
--谓词传递闭包(不支持)SQL> explain select * from emp where emp_id>dept_id and dept_id>900;1   #NSET2: [1, 25, 163]2     #PRJT2: [1, 25, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 25, 163]; (EMP.DEPT_ID > var1 AND EMP.EMP_ID > EMP.DEPT_ID) SLCT_PUSHDOWN(TRUE)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP) NEED_SLCT(TRUE); btr_scan(1)   -- 等价合取范式(支持)SQL> explain select * from emp where (0>1) and dept_id=10;1   #NSET2: [1, 1, 163]2     #PRJT2: [1, 1, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 1, 163];  FALSE4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP); btr_scan(1)   -- AND 操作符交换(支持)SQL> explain select * from emp where dept_id+emp_id=1000 and salary>900;1   #NSET2: [1, 225, 163]2     #PRJT2: [1, 225, 163]; exp_num(6), is_atom(FALSE)3       #SLCT2: [1, 225, 163]; (EMP.SALARY > var1 AND EMP.DEPT_ID+EMP.EMP_ID = var2)4         #CSCN2: [1, 10000, 163]; INDEX33555484(EMP); btr_scan(1)
-- MySQL
-- Having 并入 Where(未改写)mysql> explain SELECT * FROM emp where dept_id=100 HAVING salary > 5000;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    10.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` = 100) having (`testdb`.`emp`.`salary` > 5000) |+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
--去除冗余括号mysql> explain SELECT * FROM emp WHERE ((dept_id=2));+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    10.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message                                                                                                                                        |+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` = 2) |+-------+------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- 常量传递(支持)mysql> explain select * from emp where dept_id=10 and emp_id=dept_id;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra         |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------+|  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE noticed after reading const tables |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-----------------------------------------------------+
-- 消除死码(支持)mysql> explain select * from emp where (0>1) or dept_id=10;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    10.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` = 10) |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- 表达式计算(支持)mysql> explain select * from emp where dept_id=1+2;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    10.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (`testdb`.`emp`.`dept_id` = <cache>((1 + 2))) |+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- 等式变换(不支持)mysql> explain select * from emp where -dept_id=-10;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |   100.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.01 sec)
mysql> show warnings;+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (-(`testdb`.`emp`.`dept_id`) = <cache>(-(10))) |+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- 不等式转换(不支持)mysql> explain select * from emp where salary >1100 and salary>2000;+----+-------------+-------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+| id | select_type | table | partitions | type  | possible_keys  | key            | key_len | ref  | rows | filtered | Extra                 |+----+-------------+-------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+|  1 | SIMPLE      | emp   | NULL       | range | idx_emp_salary | idx_emp_salary | 5       | NULL |  421 |   100.00 | Using index condition |+----+-------------+-------+------------+-------+----------------+----------------+---------+------+------+----------+-----------------------+1 row in set, 1 warning (0.01 sec)
mysql> show warnings;+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where ((`testdb`.`emp`.`salary` > 1100) and (`testdb`.`emp`.`salary` > 2000)) |+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
--谓词传递闭包(不支持)mysql> explain select * from emp where emp_id>dept_id and dept_id>900;+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 10117 |    11.11 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.01 sec)
mysql> show warnings;+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where ((`testdb`.`emp`.`emp_id` > `testdb`.`emp`.`dept_id`) and (`testdb`.`emp`.`dept_id` > 900)) |+-------+------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- 等价合取范式(支持)mysql> explain select * from emp where (0>1) and dept_id=10;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra            |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+|  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | Impossible WHERE |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+------------------+1 row in set, 1 warning (0.00 sec)
mysql> show warnings;+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where false |+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- AND 操作符交换(支持)mysql> explain select * from emp where dept_id+emp_id=1000 and salary>900;+----+-------------+-------+------------+------+----------------+------+---------+------+-------+----------+-------------+| id | select_type | table | partitions | type | possible_keys  | key  | key_len | ref  | rows  | filtered | Extra       |+----+-------------+-------+------------+------+----------------+------+---------+------+-------+----------+-------------+|  1 | SIMPLE      | emp   | NULL       | ALL  | idx_emp_salary | NULL | NULL    | NULL | 10117 |    88.96 | Using where |+----+-------------+-------+------------+------+----------------+------+---------+------+-------+----------+-------------+1 row in set, 1 warning (0.01 sec)
mysql> show warnings;+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Level | Code | Message                                                       |+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| Note  | 1003 | /* select#1 */ select `testdb`.`emp`.`emp_id` AS `emp_id`,`testdb`.`emp`.`dept_id` AS `dept_id`,`testdb`.`emp`.`emp_name` AS `emp_name`,`testdb`.`emp`.`birthday` AS `birthday`,`testdb`.`emp`.`salary` AS `salary` from `testdb`.`emp` where (((`testdb`.`emp`.`dept_id` + `testdb`.`emp`.`emp_id`) = 1000) and (`testdb`.`emp`.`salary` > 900)) |+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
-- KingBase-- Having 并入 Where(不支持)TEST=# explain SELECT * FROM emp where dept_id=100 HAVING salary > 5000;ERROR:  column "emp.emp_id" must appear in the GROUP BY clause or be used in an aggregate function
--去除冗余括号TEST=# explain SELECT * FROM emp WHERE ((dept_id=2));                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..17401.03 rows=10167 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..15384.33 rows=4236 width=42)         Filter: (dept_id = '2'::numeric)
-- 常量传递(支持)TEST=# explain select * from emp where dept_id=10 and emp_id=dept_id;                            QUERY PLAN------------------------------------------------------------------- Index Scan using EMP_PK on emp  (cost=0.42..8.45 rows=1 width=42)   Index Cond: (emp_id = '10'::numeric)   Filter: (dept_id = '10'::numeric)   -- 消除死码(支持)TEST=# explain select * from emp where (0>1) or dept_id=10;                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..17377.63 rows=9933 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..15384.33 rows=4139 width=42)         Filter: (dept_id = '10'::numeric)
-- 表达式计算(支持)TEST=# explain select * from emp where dept_id=1+2;                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..17447.63 rows=10633 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..15384.33 rows=4430 width=42)         Filter: (dept_id = '3'::numeric)
-- 等式变换(不支持)TEST=# explain select * from emp where -dept_id=-10;                                QUERY PLAN-------------------------------------------------------------------------- Gather  (cost=1000.00..17926.00 rows=5000 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..16426.00 rows=2083 width=42)         Filter: ((- dept_id) = '-10'::numeric)
-- 不等式转换(支持)TEST=#  explain select * from emp where salary >1100 and salary>2000;                                QUERY PLAN--------------------------------------------------------------------------- Index Scan using idx_emp_salary on emp  (cost=0.42..8.44 rows=1 width=42)   Index Cond: (salary > '2000'::double precision)
-- 谓词传递闭包(不支持)TEST=# explain select * from emp where emp_id>dept_id and dept_id>900;                               QUERY PLAN------------------------------------------------------------------------ Gather  (cost=1000.00..17429.00 rows=30 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..16426.00 rows=12 width=42)         Filter: ((emp_id > dept_id) AND (dept_id > '900'::numeric))
-- 等价合取范式(支持)TEST=# explain select * from emp where (0>1) and dept_id=10;                QUERY PLAN------------------------------------------ Result  (cost=0.00..0.00 rows=0 width=0)   One-Time Filter: false
-- AND 操作符交换(支持)TEST=# explain select * from emp where dept_id+emp_id=1000 and salary>900;                                           QUERY PLAN------------------------------------------------------------------------------------------------- Gather  (cost=1000.00..18919.77 rows=4521 width=42)   Workers Planned: 2   ->  Parallel Seq Scan on emp  (cost=0.00..17467.67 rows=1884 width=42)         Filter: ((salary > '900'::double precision) AND ((dept_id + emp_id) = '1000'::numeric))         -- YashanDB-- Having 并入 Where(不支持)SQL> explain SELECT * FROM emp where dept_id=100 HAVING salary > 5000[1:52]YAS-04316 not a single-group group function
--去除冗余括号(支持)SQL> explain SELECT * FROM emp WHERE ((dept_id=2));+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |        89|       46( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 2)   -- 常量传递(不支持)SQL> explain select * from emp where dept_id=10 and emp_id=dept_id;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |         1|       47( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."EMP_ID" = "EMP"."DEPT_ID" AND 10 = "EMP"."DEPT_ID")   -- 消除死码(支持)SQL> explain select * from emp where (0>1) or dept_id=10;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |        99|       46( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 10)   -- 表达式计算(支持)SQL> explain select * from emp where dept_id=1+2;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |       114|       46( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 3)   -- 等式变换(支持)SQL> explain select * from emp where -dept_id=-10;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |        99|       46( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" = 10)   -- 不等式转换(支持)SQL> explain select * from emp where salary >1100 and salary>2000;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||  1 |  TABLE ACCESS BY INDEX ROWID   | EMP                  | TESTUSER   |         1|        1( 0)|                                ||* 2 |   INDEX RANGE SCAN             | IDX_EMP_SALARY       | TESTUSER   |         1|        1( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   2 - Predicate : access("EMP"."SALARY" > 2000)     --谓词传递闭包(支持)SQL> explain select * from emp where emp_id>dept_id and dept_id>900;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |         1|       47( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID" > 900 AND "EMP"."EMP_ID" > 900 AND "EMP"."EMP_ID" > "EMP"."DEPT_ID")   -- 等价合取范式(支持)SQL> explain select * from emp where (0>1) and dept_id=10;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  RESULT                        |                      |            |          |        1( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter(FALSE)   -- AND 操作符交换(不支持)SQL> explain select * from emp where dept_id+emp_id=1000 and salary>900;+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+| Id | Operation type                 | Name                 | Owner      | Rows     | Cost(%CPU)  | Partition info                 |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+|  0 | SELECT STATEMENT               |                      |            |          |             |                                ||* 1 |  TABLE ACCESS FULL             | EMP                  | TESTUSER   |        10|       47( 0)|                                |+----+--------------------------------+----------------------+------------+----------+-------------+--------------------------------+Operation Information (identified by operation id):---------------------------------------------------   1 - Predicate : filter("EMP"."DEPT_ID"+"EMP"."EMP_ID" = 1000 AND "EMP"."SALARY" > 900)   -- Vastbase-- Having 并入 Where(不支持)vastbase=> explain SELECT * FROM emp where dept_id=100 HAVING salary > 5000;ERROR:  column "emp.emp_id" must appear in the GROUP BY clause or be used in an aggregate functionLINE 1: explain SELECT * FROM emp where dept_id=100 HAVING salary > ...
--去除冗余括号(支持)vastbase=> explain SELECT * FROM emp WHERE ((dept_id=2));                       QUERY PLAN-------------------------------------------------------- Seq Scan on emp  (cost=0.00..243.00 rows=106 width=44)   Filter: (dept_id = 2::number)
-- 常量传递(支持)vastbase=> explain select * from emp where dept_id=10 and emp_id=dept_id;                            QUERY PLAN------------------------------------------------------------------- Index Scan using emp_pk on emp  (cost=0.00..8.27 rows=1 width=44)   Index Cond: (emp_id = 10::number)   Filter: (dept_id = 10::number)   -- 消除死码(支持)vastbase=> explain select * from emp where (0>1) or dept_id=10;                      QUERY PLAN------------------------------------------------------- Seq Scan on emp  (cost=0.00..243.00 rows=91 width=44)   Filter: (dept_id = 10::number)
-- 表达式计算(支持)vastbase=> explain select * from emp where dept_id=1+2;                      QUERY PLAN------------------------------------------------------- Seq Scan on emp  (cost=0.00..243.00 rows=91 width=44)   Filter: (dept_id = 3::number)
-- 等式变换(不支持)vastbase=> explain select * from emp where -dept_id=-10;                      QUERY PLAN------------------------------------------------------- Seq Scan on emp  (cost=0.00..268.00 rows=50 width=44)   Filter: ((- dept_id) = (-10)::number)
-- 不等式转换(不支持)vastbase=> explain select * from emp where salary >1100 and salary>2000;                                       QUERY PLAN----------------------------------------------------------------------------------------- Index Scan using idx_emp_salary on emp  (cost=0.00..8.27 rows=1 width=44)   Index Cond: ((salary > 1100::double precision) AND (salary > 2000::double precision))
-- 谓词传递闭包(不支持)vastbase=> explain select * from emp where emp_id>dept_id and dept_id>900;                         QUERY PLAN------------------------------------------------------------ Seq Scan on emp  (cost=0.00..268.00 rows=1 width=44)   Filter: ((emp_id > dept_id) AND (dept_id > 900::number))
-- 等价合取范式(支持)vastbase=> explain select * from emp where (0>1) and dept_id=10;                         QUERY PLAN------------------------------------------------------------ Result  (cost=0.00..218.00 rows=1 width=44)   One-Time Filter: false   ->  Seq Scan on emp  (cost=0.00..218.00 rows=1 width=44)
-- AND 操作符交换(支持)vastbase=> explain select * from emp where dept_id+emp_id=1000 and salary>900;                                      QUERY PLAN-------------------------------------------------------------------------------------- Seq Scan on emp  (cost=0.00..293.00 rows=45 width=44)   Filter: ((salary > 900::double precision) AND ((dept_id + emp_id) = 1000::number))

3. 逻辑优化—连接消除

在多表连接的过程中,查询优化器可以找出多表连接的最优查询执行计划,这意味着多个表的最优的连接次序被确定。如果根据表的连接次序确定析取条件的优先判断次序,存在加速判断的可能(处于表达式后面的条件可能不用判断了)。

1).优化规则

5.png5.png

2).数据库支持情况

6.png6.png

3).数据库测评

受篇幅限制,略去操作部分。

4. 逻辑优化—索引优化

如果语句中不仅包含有Select(选择)、Project(投影)、Join(连接) 三种基础操作,还有其他类操作(如分组等)。此时,优化器是可以根据索引进行一定的优化。

1).优化规则

7.png7.png

2).数据库支持情况

8.png8.png

3).数据库测评

受篇幅限制,略去操作部分。

责任编辑:武晓燕 来源: 韩锋频道
相关推荐

2024-12-04 08:44:25

OS集中式数据库

2022-06-06 07:32:44

数据库系统分布式

2025-01-09 07:30:49

SQL能力评测

2023-11-27 08:33:42

2024-12-19 07:30:34

2024-12-10 07:30:46

2012-02-23 23:33:37

开源memcached

2023-08-22 14:20:21

2024-12-05 07:31:16

2024-12-26 07:33:02

2015-07-28 09:44:38

集中式云数据加密安全漏洞

2019-11-07 11:21:21

安全软件IT

2022-03-29 14:28:03

架构安全设计

2012-02-21 09:59:52

2009-07-02 19:24:50

安全管理Windows审计

2011-10-19 13:53:11

2009-07-20 11:11:34

分光器FTTP

2023-12-27 14:05:00

关系型数据库产品

2020-08-19 17:56:46

缓存Redis集中式

2022-02-09 10:52:27

智能汽车网联
点赞
收藏

51CTO技术栈公众号