"or" and "( )" make execution plan difference

本文探讨了在Oracle数据库中针对特定查询语句的执行计划进行优化的方法。通过对查询条件的不同构造方式,展示了如何通过调整来获得更优的查询性能。具体包括使用函数索引、避免全表扫描及利用位图转换等技巧。

    test_c as 1160 rows.It has a columan called "STRDHHM".a function index is created in the column "STRDHHM".The statment is like that:
    create index IND_AUTO_CUSTOMERJUDGE_1 on TEST_C (LTRIM(STRDHHM,'0')) tablespace USERS;
    The distinct LTRIM(STRDHHM,'0') values is 1130.And test_c has been analyzed.
    when I use this query statement,It goes "table access full" or "BITMAP CONVERSION":
_____________________________________________________
    EXPLAIN PLAN FOR
SELECT *
  from test_c c
 where (LTRIM(STRDHHM,'0') = LTRIM('18999912345', '0') AND type = '1')
    OR
       ((LTRIM(STRDHHM,'0')=substr(LTRIM('18999912345', '0'), 1, 3)) AND type = '2')
   and (sysdate - dtjudgedate) * 1440 <= inthmdlimit
   and inthmdflag = 1;
SELECT * from TABLE(dbms_xplan.display) 
________________________________________________________
Plan hash value: 1554345677
 
-------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                          |     1 |    48 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS BY INDEX ROWID     | TEST_C                   |     1 |    48 |     3   (0)| 00:00:01 |
|   2 |   BITMAP CONVERSION TO ROWIDS    |                          |       |       |            |          |
|   3 |    BITMAP OR                     |                          |       |       |            |          |
|   4 |     BITMAP CONVERSION FROM ROWIDS|                          |       |       |            |          |
|*  5 |      INDEX RANGE SCAN            | IND_AUTO_CUSTOMERJUDGE_1 |       |       |     1   (0)| 00:00:01 |
|   6 |     BITMAP CONVERSION FROM ROWIDS|                          |       |       |            |          |
|*  7 |      INDEX RANGE SCAN            | IND_AUTO_CUSTOMERJUDGE_1 |       |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   1 - filter("TYPE"='1' AND LTRIM("STRDHHM",'0')='18999912345' OR "INTHMDFLAG"=1 AND "TYPE"='2' AND
              LTRIM("STRDHHM",'0')='189' AND "INTHMDLIMIT">=(SYSDATE@!-"DTJUDGEDATE")*1440)
   5 - access(LTRIM("STRDHHM",'0')='18999912345')
   7 - access(LTRIM("STRDHHM",'0')='189')
   _________________________________________________________
    when I carry () in  the both size of "or" statement,It goes "INLIST ITERATOR" what is I want:
   _______________________________________________________
EXPLAIN PLAN FOR
SELECT COUNT(*)
  from test_c c
 where ((LTRIM(STRDHHM,'0') = LTRIM('18999912345', '0') AND type = '1')
    OR
       ((LTRIM(STRDHHM,'0')=substr(LTRIM('18999912345', '0'), 1, 3)) AND type = '2'))
   and (sysdate - dtjudgedate) * 1440 <= inthmdlimit
   and inthmdflag = 1;
SELECT * from TABLE(dbms_xplan.display)
_________________________________________________
Plan hash value: 2951030008
 
----------------------------------------------------------------------------------------------------------
| Id  | Operation                     | Name                     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                          |     1 |    48 |     3   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE               |                          |     1 |    48 |            |          |
|   2 |   INLIST ITERATOR             |                          |       |       |            |          |
|*  3 |    TABLE ACCESS BY INDEX ROWID| TEST_C                   |     1 |    48 |     3   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN          | IND_AUTO_CUSTOMERJUDGE_1 |     2 |       |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
 
   3 - filter("INTHMDFLAG"=1 AND ("TYPE"='1' AND LTRIM("STRDHHM",'0')='18999912345' OR "TYPE"='2'
              AND LTRIM("STRDHHM",'0')='189') AND "INTHMDLIMIT">=(SYSDATE@!-"DTJUDGEDATE")*1440)
   4 - access(LTRIM("STRDHHM",'0')='18999912345' OR LTRIM("STRDHHM",'0')='189')
   

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14730395/viewspace-673128/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/14730395/viewspace-673128/

### 回答1: 好的,下面我来写一个简单的 Execution Plan 的 demo: 假设我们有一个表 `users`,其中包含以下字段:`id`、`name`、`age`、`gender`。 我们现在想要查询年龄小于等于 30 岁的女性用户,按照年龄从小到大排序。 具体操作如下: 1. 创建索引 ```sql CREATE INDEX age_index ON users(age); CREATE INDEX gender_index ON users(gender); ``` 2. 编写 Execution Plan ```sql EXPLAIN SELECT id, name, age, gender FROM users WHERE age <= 30 AND gender = 'female' ORDER BY age ASC; ``` 3. 执行查询 ```sql SELECT id, name, age, gender FROM users WHERE age <= 30 AND gender = 'female' ORDER BY age ASC; ``` 4. 解释 Execution Plan 解释结果如下: ``` id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE users NULL range age_index,gender_index age_index 5 NULL 1 100.00 Using index condition; Using filesort ``` 其中,重要的字段解释如下: - `select_type`: 查询类型,这里是 SIMPLE,表示单表查询。 - `table`: 查询的表名。 - `type`: 访问类型,这里是 range,表示使用索引范围扫描。 - `possible_keys`: 可能使用的索引,这里是 age_index 和 gender_index。 - `key`: 实际使用的索引,这里是 age_index。 - `key_len`: 使用索引的长度,这里是 5,表示 age 字段需要占用 4 个字节,再加上一个字符用于比较操作。 - `ref`: 使用索引的列。 - `rows`: 预估扫描的行数。 - `filtered`: 过滤后的行数占比。 - `Extra`: 额外的信息,这里是 Using index condition 和 Using filesort。 通过解释结果可以看到,查询时使用了 age_index 索引,而不是 gender_index 索引。同时,查询时使用了索引条件,过滤掉了大部分不符合条件的行。最后,使用了 filesort 对结果进行排序。 ### 回答2: Execution Plan是用于优化和调优SQL语句性能的工具,它主要用于分析SQL查询语句在数据库中的执行计划。下面是一个使用Execution Plan的demo的简单示例: 假设我们有一个名为"employees"的员工表,表结构如下: ``` CREATE TABLE employees ( id INT PRIMARY KEY, name VARCHAR(50), age INT, department VARCHAR(50), salary DECIMAL(10, 2) ); ``` 我们需要查询"salary"字段大于等于5000的员工信息,并按照"salary"字段降序排列。 使用Execution Plan,我们可以先执行以下语句开启执行计划: ``` EXPLAIN ANALYZE SELECT * FROM employees WHERE salary >= 5000 ORDER BY salary DESC; ``` 执行完成后,我们可以获得查询的执行计划,执行计划将显示查询的执行步骤和所需的资源消耗,以及可能存在的性能瓶颈。例如,执行计划可能会显示是否使用了索引、是否进行了表扫描等信息。 接下来,我们可以根据执行计划进行优化查询语句。例如,我们可以查看是否使用了索引,如果没有使用索引,我们可以考虑创建合适的索引以提高查询性能。我们也可以查看是否存在表扫描等性能瓶颈,并考虑使用合适的优化方法解决这些问题。 在这个例子中,假设执行计划显示了"salary"字段上的索引没有被使用,那么我们可以创建一个适当的索引来加速查询: ``` CREATE INDEX idx_salary ON employees (salary DESC); ``` 然后,我们再次执行查询语句并开启执行计划,查看优化后的执行计划是否有所改善。 通过以上的方法,我们可以使用Execution Plan工具来优化和调优SQL语句性能,提高数据库查询效率。 ### 回答3: 使用Execution Plan编写一个demo可以帮助我们理解如何优化SQL查询。 首先,我们需要创建一个表来演示。假设我们有一个员工表,包含字段:员工ID、姓名、年龄和工资。 ``` CREATE TABLE Employee ( EmployeeID INT PRIMARY KEY, Name VARCHAR(50), Age INT, Salary DECIMAL(10, 2) ); ``` 接下来,我们可以插入一些示例数据。 ``` INSERT INTO Employee (EmployeeID, Name, Age, Salary) VALUES (1, '张三', 25, 5000.00), (2, '李四', 30, 6000.00), (3, '王五', 35, 7000.00), (4, '赵六', 40, 8000.00); ``` 现在,让我们来编写查询代码,并查看对应的执行计划。 ``` EXPLAIN SELECT * FROM Employee WHERE Age > 30; ``` 执行此查询,我们将会得到一个查询执行计划。该计划将告诉我们在执行查询时数据库要采取的步骤。 我们可以通过解读执行计划来优化查询。比如,我们可以注意到上述查询使用了全表扫描,这可能效率较低。为了优化这个查询,我们可以使用索引。 我们可以添加一个索引来提高年龄查询的性能。 ``` CREATE INDEX idx_Employee_Age ON Employee (Age); ``` 现在,我们再次执行相同的查询并查看执行计划。 ``` EXPLAIN SELECT * FROM Employee WHERE Age > 30; ``` 我们可以看到执行计划已经改变,它将使用索引来加快查询速度。 通过使用Execution Plan,我们可以了解查询如何执行,并根据需要进行优化。这有助于提高数据库的性能和查询效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值