自己在学习oracle优化课程的时候,想当然的以为count(*) 操作肯定是会走索引的。可是那天碰巧试试发现居然是全表扫描。
这里把关于这个问题的解决的过程记录下来,以便以后查阅,也希望能给同时遇见这个问题的朋友一点帮助。
--打开执行计划
SQL> set autotrace traceonly
--刚开使的查询计划
SQL> select count(*) from emp;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP'
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
376 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
-- 使用 hints 仍然是全表扫描
SQL> select /*+ index(PK_EMP) */ count(*) from emp;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1)
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=82)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
376 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
--分析表
SQL> analyze table emp compute statistics;
表已分析。
-- 再次执行 则开始走索引
SQL> select count(*) from emp;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=1 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FULL SCAN) OF 'PK_EMP' (UNIQUE) (Cost=1 Card=14)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1 consistent gets
0 physical reads
0 redo size
376 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
问题解决,但仍有许多需要解释一下的地方。
1. rbo与cbo
rbo是基于规则的,在rbo下需要程序员自己分析然后指定应该使用那一个索引效率更高,也就是要使用hints。 而在cbo是基于cost的,这样sql引擎会自己计算用那个索引的cost最小,然后选择该索引执行sql语句。但是cbo需要有表的统计信息。
rbo是oracle早期版本7i的特性,8i,9i是即支持rbo也支持cbo的 但oracle 10g就只有cbo了,所以在10g中oracle会自己对表进行分析,并保存表的统计信息。
所以在没有对表进行分析的时候 走 rbo, 分析过的表走 cbo
2. 索引中不能含有null值,如果建索引的列不是 not null的,那么索引将不被使用。
其它索引不被使用的情况:
1)当对同一个表的两个列(其中一个列为主键,一个列为索引) 进行比较时,索引有时不会被使用
2)在where中出现 is null或者is not null时 索引不能被使用
3)在where语句中存在有not function时 例:not in,not exist,<>,>,<等情形下索引不能被使用
4)当使用了single-row function时 例nvl,to_char,lower等索引不能被使用
5)当使用通配符号%或者_作为查询字符串的第一个字符时索引不会被使用
分享到:
相关推荐
- **示例**: `PREPARE EmpSelect FROM 'SELECT * FROM Employees WHERE ID = ?';` #### 执行语句 (EXECUTE) - **语法**: `EXECUTE statement_name USING variable_list;` - **功能**: 用于执行准备好的动态SQL语句...
### SQL语句SELECT用法详解 #### 一、概述 SQL(Structured Query Language)是一种用于管理关系数据库的标准语言。在SQL中,`SELECT`语句是最常用的操作之一,主要用于从数据库表中检索数据。通过使用不同的子句...
- **示例**:将 `SELECT * FROM EMP WHERE EMPNO IN (SELECT DEPTNO FROM DEPT WHERE LOC = 'MELB')` 替换为 `SELECT * FROM EMP WHERE EXISTS (SELECT NULL FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND DEPT....
### 自己收藏的经典SQL语句 #### 数据库操作 **1. 创建数据库** - **命令格式**: `CREATE DATABASE database-name;` - **说明**: 此命令用于创建一个新的数据库。 - **示例**: `CREATE DATABASE myDatabase;` ...
SELECT COUNT(1) FROM EMP E2 WHERE E2.DEPTNO = E1.DEPTNO AND E2.ENAME != E1.ENAME AND E2.SAL >= E1.SAL ) ; ``` **解析:** 这是一个较为复杂的查询,使用了子查询和比较条件来找出每个部门中除了自身之外...
- **示例**:`SELECT * FROM table WHERE (SELECT COUNT(*) FROM other_table WHERE other_table.id = table.id) > 0;` #### 十七、用WHERE子句替换HAVING子句 - **优化建议**:尽可能在WHERE子句中过滤数据,以...
SELECT...FROM EMPE WHERE SAL > 50000 AND JOB = 'MANAGER' AND 25 (SELECT COUNT(*) FROM EMP WHERE MGR = E.EMPNO); ``` **高效版本**: ```sql SELECT...FROM EMPE WHERE 25 (SELECT COUNT(*) FROM EMP WHERE ...
- **大小写不敏感**: SQL语句在大多数数据库系统中对大小写不敏感,但为了提高代码的可读性和一致性,建议统一使用大写或小写字母来书写SQL关键字。 - **多行书写**: SQL语句可以跨多行书写,以增强可读性。 - **...
- SQL语句示例:`SELECT deptno, COUNT(*) AS emp_count FROM emp GROUP BY deptno HAVING COUNT(*) >= 1;` - **列出各个部门的MANAGER(经理)的最低薪金。** - 首先需要确定经理的职位,假设为“MANAGER”。 -...
### SQL语句学习教程知识点概览 #### 一、SQL*PLUS工具软件的使用 - **定义**:SQL*Plus是Oracle提供的一款用于执行SQL语句的命令行工具,是Oracle数据库管理员常用的工具之一。 - **功能**: - 执行SQL语句 - ...
SELECT * FROM emp WHERE idcard LIKE '%X'; -- 查询最后一位身份证号是X的员工 ``` - **聚合函数**: | 函数 | 功能 | | --- | --- | | COUNT | 统计数量 | | MAX | 最大值 | | MIN | 最小值 | | AVG | ...
### 对于RULE优化器的一些SQL语句的优化方法 #### 一、理解RULE优化器及其在SQL查询中的作用 在数据库管理系统(DBMS)中,查询优化器是负责选择执行查询的最佳策略的关键组件之一。根据不同的优化算法,优化器...
Select count(*) from scott.emp; ``` - 查询每个部门的部门代码、薪水之和、平均薪水: ```sql Select empID, sum(laborage) as "薪水之和", avg(laborage) as "平均薪水" from emp group by empID; ``` 6. ...
WHERE E.ROWID = (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO); ``` ### 4. TRUNCATE VS DELETE #### 知识点: - `TRUNCATE`操作会删除表中的所有数据,但不会记录任何日志信息,因此执行速度非常...
- **使用 EXPLAIN 分析**:大多数数据库管理系统提供了`EXPLAIN`命令来查看SQL语句的执行计划,这对于理解查询是如何被执行的以及如何优化非常有帮助。 - **I/O 操作估计**:通过对执行计划中I/O操作的估计,可以...
9. **数据库分组查询**:在 SQL 中,使用 GROUP BY 语句进行分组查询时,任何在 SELECT 列表中非分组函数的列都必须出现在 GROUP BY 子句中。分组函数如 COUNT、SUM、AVG 等会忽略 NULL 值,并且只能出现在 SELECT ...