由于B*Tree索引不存储Null值,所以在索引字段允许为空的情况下,某些Oracle查询不会使用索引.
很多时候,我们看似可以使用全索引扫描(Full Index Scan)的情况,可能Oracle就会因为Null值的存在而放弃索引.
在此情况下即使使用Hints,Oracle也不会使用索引,其根本原因就是因为Null值的存在.
我们看以下测试.
在username字段为Not Null时,Index Hints可以生效.
SQL> create table t as select username,password from dba_users; Table created. SQL> desc t Name Null? Type ----------------------------------------- -------- ---------------------------- USERNAME NOT NULL VARCHAR2(30) PASSWORD VARCHAR2(30) SQL> create index i_t on t(username); Index created. SQL> set autotrace trace explain SQL> select * from t where username='EYGLE'; Execution Plan ---------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 34 | 2 (0)| 00:00:01 | |* 1 | TABLE ACCESS FULL| T | 1 | 34 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 1 - filter("USERNAME"='EYGLE') Note ----- - dynamic sampling used for this statement SQL> set linesize 120 SQL> select /*+ index(t,i_t) */ * from t where username='EYGLE'; Execution Plan ---------------------------------------------------------- Plan hash value: 2928007915 ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 34 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 34 | 2 (0)| 00:00:01 | |* 2 | INDEX RANGE SCAN | I_T | 1 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("USERNAME"='EYGLE') Note ----- - dynamic sampling used for this statement |
当索引字段允许为Null时,Oracle放弃此索引:
SQL> alter table t modify (username null); Table altered. SQL> select /*+ index(t,i_t) */ * from t; Execution Plan ---------------------------------------------------------- Plan hash value: 1601196873 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 27 | 918 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T | 27 | 918 | 2 (0)| 00:00:01 | -------------------------------------------------------------------------- Note ----- - dynamic sampling used for this statement |
当该字段为Not Null时,索引可以被强制使用:
SQL> alter table t modify (username not null); Table altered. SQL> select /*+ index(t,i_t) */ * from t; Execution Plan ---------------------------------------------------------- Plan hash value: 3593393735 ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 27 | 918 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| T | 27 | 918 | 2 (0)| 00:00:01 | | 2 | INDEX FULL SCAN | I_T | 27 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------ Note ----- - dynamic sampling used for this statement |
这就是Null值对于索引及查询的影响.
相关推荐
### Oracle数据库关于SQL的执行计划 #### 1. Oracle 的 Optimizer 及其相关知识 在 Oracle 数据库中,执行 SQL 查询之前会先生成一个执行计划(Execution Plan),该计划由 Oracle 的优化器(Optimizer)根据一...
- **稀疏索引**:对于含有大量NULL值的列,稀疏索引可以节省存储空间。 - **非聚集覆盖索引**:这种索引不包含表的所有列,但包含查询所需的特定列,可以减少I/O操作。 7. **索引维护和调优**: - 定期执行索引...
优化过程通常包括定位性能差的语句、检查执行计划、分析统计信息、检查记录数和索引情况等步骤。作者强调,SQL调优是一个系统工程,需要全面考虑SQL的结构和数据库的工作原理。 在提高查询效率方面,文章提出了利用...
NULL值在数据库中的处理方式与非NULL值不同,它们可能导致不必要的计算和效率降低。在实际的SQL语句中,我们需要注意如何正确地使用NULL值,避免在条件判断中产生误判或者增加计算负担。例如,使用`IS NULL`或`IS ...
使用SQL提示(Hints)来指导优化器使用特定的执行计划。 2. 创建SQL Profile来存储优化过的执行计划,确保每次查询都使用相同的计划。 3. 利用SQL Plan Management(SPM)特性来管理执行计划版本。 #### 十、...
4. **Oracle Hints的使用**:虽然可以直接控制执行计划,但需谨慎使用,并定期评估其对系统性能的影响。 综上所述,SQL优化是一项复杂而细致的工作,需要结合实际应用场景灵活运用各种技术和方法。只有不断实践与...
- **使用hints**:通过在SQL语句中添加注释形式的hints,可以直接控制执行计划的选择。 #### 七、具体案例分析 通过对实际场景中的SQL查询进行案例分析,可以帮助我们更好地理解和实践SQL性能调整的技术和方法。 ...
9. **查询优化器HINTs**:在SQL语句中使用HINTs可以强制优化器使用特定的执行计划,但这需要谨慎使用,避免过度依赖。 10. **数据库架构优化**:合理设计表分区,根据业务特点选择合适的分区策略,如范围分区、列表...
- 绑定变量用于减少解析开销,提高性能,但可能影响执行计划的选择。 13. **索引查询的性能**: - 不总是能提高查询性能,如果查询条件不符合索引,或数据分布不均,可能反而降低性能。 14. **性能指标**: - ...
1. **优化器**:Oracle的查询优化器是数据库性能的关键组件,它负责选择最优的执行计划。优化器有两种主要类型:基于规则的优化器(RBO)和基于成本的优化器(CBO)。从Oracle 9i版本开始,CBO逐渐成为默认选择,...
3. **使用 IS NULL 和 IS NOT NULL**:对于NULL值的查询,建议使用 `IS NULL` 和 `IS NOT NULL` 操作符,而不是使用 `= NULL` 或 `<> NULL`,因为后者会导致全表扫描。 4. **NOT IN 和 EXISTS 的使用**:在进行子...
在WHERE子句中使用`IS NULL`或`IS NOT NULL`会导致Oracle优化器无法利用索引进行优化,因为NULL值并不参与索引排序。为了充分利用索引,应避免在WHERE子句中使用这类条件,除非确实需要检查NULL值的存在。 ##### ...
在SQL语句中使用Hints可以指导优化器选择特定的执行计划,这对于复杂的查询特别有用。 #### 31. 用WHERE替代ORDER BY 在某些场景下,使用WHERE子句过滤数据后再进行ORDER BY操作可以减少排序的工作量,从而提高...
22. **避免在索引列上使用NULL值**:NULL值在索引中处理特殊,可能影响性能。 23. **使用索引合并策略**:当有多个可能的索引时,Oracle会尝试合并它们。 24. **注意行链接顺序**:JOIN操作中,先链接小表可以提高...
【知识点详解】 1. Oracle数据库查询优化:Oracle数据库在执行SQL查询时,会根据...6. 稳定执行计划:通过绑定变量、使用SQL profile或SQL plan baseline来固定执行计划,避免因统计信息变化导致的执行计划不稳定。
2. 查询优化器关注的主要是执行计划的选择,以及如何减少I/O操作、优化索引使用、合理利用缓存等。 3. 查看执行计划可通过EXPLAIN PLAN或设置SQL_TRACE,查看执行计划的详细信息。 4. 索引对写操作有负面影响,...
定期更新表的统计信息,确保优化器能够做出准确的执行计划,避免过度或不足的索引使用。 通过以上十八掌,你可以对SQL语句进行深度优化,实现数据库性能的最大化。但请记住,每个数据库系统都有其特性和最佳实践,...
- **建议**:在必要时合理使用HINTs来优化执行计划。 12. **DISTINCT与GROUP BY的使用** - `DISTINCT`关键字用于返回唯一不同的值。 - `GROUP BY`用于对数据进行分组。 - 在某些情况下,`GROUP BY`可以作为`...
20. **使用 TKPROF 工具**:通过 TKPROF 分析 SQL 执行计划,找出性能瓶颈。 21. **用 EXPLAIN PLAN 分析 SQL 语句**:EXPLAIN PLAN 可以显示 Oracle 选择的执行路径,帮助优化查询。 22. **使用索引提高效率**:...
- 调整`OPTIMIZER_USE_PLSQL_FUNCTION_HINTS`参数,让CBO能够利用函数提示来优化执行计划。 #### 4. 约束条件 约束条件对于CBO的决策非常重要,它们可以提供关于表结构的重要信息,帮助优化器做出更好的选择。例如...