`

如何避免oracle全表扫描

阅读更多

1. 对返回的行无任何限定条件,即没有where 子句

 

 

2. 未对数据表与任何索引主列相对应的行限定条件

例如:在City-State-Zip列创建了三列复合索引,那么仅对State列限定条件不能使用这个索引,因为State不是索引的主列。

 

3. 对索引的主列有限定条件,但是在条件表达式里使用以下表达式则会使索引失效,造成全表扫描:

1where子句中对字段进行函数、表达式操作,这将导致引擎放弃使用索引而进行全表扫描,

Demo:

where   upper(city)='TokYo'  City || 'X' like 'TOKYO%',

select id from t where num/2=100   应改为:   select id from t where num=100*2

select * from emp where to_char(hire_date,'yyyymmdd')='20080411' (不使用)

select * from emp where hire_date = to_char('20080411','yyyymmdd') (使用)

 

2查询字段is null时索引失效,引起全表扫描。

where City is null    ,where City is not null,

解决方法:SQL语法中使用NULL会有很多麻烦,最好索引列都是NOT NULL的;对于is null,可以建立组合索引,nvl(字段,0),对表和索引analyse后,is null查询时可以重新启用索引查找,但是效率还不是值得肯定;is not null 时永远不会使用索引。一般数据量大的表不要用is null查询。

select id from t where num is null

可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

select id from t where num=0

 

(3)查询条件中使用了不等于操作符(<>!=会限制索引、引起全表扫描

Where city!='TOKYO'.

解决方法:通过把不等于操作符改成or,可以使用索引,避免全表扫描。例如,把column<>’aaa’,改成column<’aaa’ or column>’aaa’,就可以使用索引了。

 

(4)对索引的主列有限定条件,但是条件使用like操作以及值%开始或者值是一个赋值变量。例如:

where City like '%YOK%'

where City like: City_bind_Variable xl_rao

select * from emp where name like '%A' (不使用索引)

select * from emp where name like 'A%' (使用索引)

解决办法:首先尽量避免模糊查询,如果因为业务需要一定要使用模糊查询,则至少保证不要使用全模糊查询,对于右模糊查询,即like ‘…%’,是会使用索引的;左模糊like ‘%...’无法直接使用索引,但可以利用reverse + function index 的形式,变化成 like ‘…%’;全模糊是无法优化的,一定要的话考虑用搜索引擎。出于降低数据库服务器的负载考虑,尽可能地减少数据库模糊查询。

4 or语句使用不当会引起全表扫描

原因:where子句中比较的两个条件,一个有索引,一个没索引,使用or则会引起全表扫描。例如:where A=1 or B=2A上有索引,B上没索引,则比较B=2时会重新开始全表扫描

 

 

5模糊查询效率很低:

  原因:like本身效率就比较低,应该尽量避免查询条件使用like;对于like%...%’(全模糊)这样的条件,是无法使用索引的,全表扫描自然效率很低;另外,由于匹配算法的关系,模糊查询的字段长度越大,模糊查询效率越低。

  解决办法:首先尽量避免模糊查询,如果因为业务需要一定要使用模糊查询,则至少保证不要使用全模糊查询,对于右模糊查询,即like‘…%’,是会使用索引的;左模糊like

  ‘%...’无法直接使用索引,但可以利用reverse + function index的形式,变化成like‘…%’;全模糊是无法优化的,一定要的话考虑用搜索引擎。出于降低数据库服务器的负载考虑,尽可能地减少数据库模糊查询。

 

6查询条件中含有is nullselect语句执行慢

   原因:Oracle 中,查询字段is null时单索引失效,引起全表扫描。

   解决方法:SQL语法中使用NULL会有很多麻烦,最好索引列都是NOT NULL的;对于is null,可以建立组合索引,nvl(字段,0),对表和索引analyse后,is null查询时可以重新启用索引查找,但是效率还不是值得肯定;is not null时永远不会使用索引。一般数据量大的表不要用is null查询。

 

7.查询条件中使用了不等于操作符(<>!=)的select语句执行慢

  原因:SQL中,不等于操作符会限制索引,引起全表扫描,即使比较的字段上有索引

   解决方法:通过把不等于操作符改成or,可以使用索引,避免全表扫描。例如,把column<>aaa’,改成column<aaaor column>aaa’,就可以使用索引了。

 

8.使用组合索引,如果查询条件中没有前导列,那么索引不起作用,会引起全表扫描;但是从Oracle9i开始,引入了索引跳跃式扫描的特性,可以允许优化器使用组合索引,即便索引的前导列没有出现在WHERE子句中。例如:create index skip1 on emp5(job,empno);   全索引扫描select count(*) from emp5 where empno=7900;   索引跳跃式扫描select /*+ index(emp5 skip1)*/ count(*) from emp5 where empno=7900;前一种是全表扫描,后一种则会使用组合索引。

9. or语句使用不当会引起全表扫描

  原因:where子句中比较的两个条件,一个有索引,一个没索引,使用or则会引起全表扫描。例如:where A=1 or B=2A上有索引,B上没索引,则比较B=2时会重新开始全表扫描。

10.组合索引,排序时应按照组合索引中各列的顺序进行排序,即使索引中只有一个列是要排序的,否则排序性能会比较差。例如:create index skip1 on emp5(job,empnodate);  select jobempno from emp5 where job=managerand empno=10order by job,empno,date desc;实际上只是查询出符合job=managerand empno=10’条件的记录并按date降序排列,但是写成order by date desc性能较差。

 

11.Update语句,如果只更改12个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。

  12.对于多张大数据量的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。

 

 13.select count(*) from table;这样不带任何条件的count会引起全表扫描,并且没有任何业务意义,是一定要杜绝的。

  14.sqlwhere条件要绑定变量,比如where column=1,不要写成where column=aaa’,这样会导致每次执行时都会重新分析,浪费CPU和内存资源。

 

15.不要使用in操作符,这样数据库会进行全表扫描,

推荐方案:在业务密集的SQL当中尽量不采用IN操作符

 

16.not in 使用not in也不会走索引

推荐方案:用not exists或者(外联结+判断为空)来代替

 

 

17.>  < 操作符(大于或小于操作符)

 

大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段 A30万记录的A=030万记录的A=139万记录的A=21万记录的A=3。那么执行A>2A>=3的效果就有很大的区别了,因为A>2ORACLE会先找出为2的记录索引再进行比较,而A>=3ORACLE则直接找到=3的记录索引。

 

 

18.UNION操作符

 

UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:

select * from gc_dfys

 

union

 

select * from ls_jg_dfys

 

这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。

 

推荐方案:采用UNION ALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。

 

19.WHERE后面的条件顺序影响

 

WHERE子句后面的条件顺序对大数据量表的查询会产生直接的影响,如

 

Select * from zl_yhjbqk where dy_dj = '1K以下' and xh_bz=1

 

Select * from zl_yhjbqk where xh_bz=1 and dy_dj = '1K以下'

 

以上两个SQLdy_djxh_bz两个字段都没进行索引,所以执行的时候都是全表扫描,第一条SQLdy_dj = '1KV以下'条件在记录集内比率为99%,而xh_bz=1的比率只为0.5%,在进行第一条SQL的时候99%条记录都进行dy_djxh_bz的比较,而在进行第二条SQL的时候0.5%条记录都进行dy_djxh_bz的比较,以此可以得出第二条SQLCPU占用率明显比第一条低。

 

20.查询表顺序的影响

 

FROM后面的表中的列表顺序会对SQL执行性能影响,在没有索引及ORACLE没有对表进行统计分析的情况下ORACLE会按表出现的顺序进行链接,由此因为表的顺序不对会产生十分耗服务器资源的数据交叉。(注:如果对表进行了统计分析,ORACLE会自动先进小表的链接,再进行大表的链接)

 

转自:http://blog.csdn.net/onetree2010/article/details/6098259

分享到:
评论

相关推荐

    oracle全表扫描的3种优化手段

    ### Oracle全表扫描的三种优化手段 在Oracle数据库管理中,全表扫描(Full Table Scan,简称FTS)是指查询语句对整个表的数据进行读取的一种操作方式。当索引选择性较差或者表较小的时候,Oracle可能会选择全表扫描...

    Oracle全表扫描及其执行计划

    Oracle全表扫描是一种数据库操作,它是访问数据库表数据的主要方式之一。当Oracle处理SQL查询时,如果选择全表扫描,那么它将遍历表中所有数据块以获取所需信息。这种扫描方式涉及到读取表中每一行,实际上,是读取...

    Oracle 表的扫描方式及连接方法

    Oracle 表的扫描方式是指 Oracle 访问表的方法,包括全表扫描、索引扫描、索引范围扫描、索引唯一扫描等。这些扫描方式的选择取决于查询的条件、索引的类型和数据的分布。 一、全表扫描(Full Table Scans, FTS) ...

    个人整理,oracle访问路径(全表扫描、回表、索引范围扫描等等)

    全表扫描是 Oracle 访问路径的一种,最基本的访问方式。它扫描整个表,检查每一行记录,以找到匹配的记录。全表扫描通常用于以下情况: * 表非常小,扫描整个表的成本较低。 * 无法使用索引,因为索引不包含查询所...

    我的案例,oracle的表

    3. **避免全表扫描**:尽可能利用索引,减少对大表的全表扫描。 4. **使用适当的连接方式**:理解并正确使用内连接、外连接和自连接,避免笛卡尔积等问题。 5. **限制返回结果集**:使用`LIMIT`或`ROWNUM`限制查询...

    oracle索引类型及扫描方式大整理

    索引的优化涉及多个方面,包括选择合适的索引类型、考虑查询模式、避免全表扫描、维护索引的粒度等。例如,对于频繁查询的列创建索引,对于低选择性的列(即大部分行有相同值的列)可能不适合创建普通索引,而更适合...

    Oracle在线建立超大表的索引

    - 减少RB的I/O:通过使用`CACHE`和`FULL`提示对源表执行全表扫描(FTS),使其尽可能多地进入buffer cache。 - 减少RC的I/O:设置更大的`SORT_AREA_SIZE`参数(若未使用PGA_AGGREGATE_TARGET则直接设置)。 - ...

    Oracle数据库中大型表查询优化的研究

    这包括正确使用索引、合理设计表结构、避免全表扫描以及有效利用分区技术。在Oracle中,索引是提高查询速度的关键,特别是B树索引和位图索引。B树索引适用于单列查询和范围查询,而位图索引则适合于多列组合查询或在...

    Oracle分区表和锁的应用

    - **表级锁(TABLE LOCK)**:锁定整个表,适用于全表扫描或批量操作。 - **行级意向锁(INTENTION LOCKS)**:用于多粒度锁定,表明接下来的锁定将是行级或表级。 2. **锁模式**: - **共享锁(SHARE LOCK)**...

    ORACLE_多表关联_UPDATE_语句

    Oracle数据库中的多表关联UPDATE语句是用于在一个表中更新数据时,依据另一个表的条件进行操作的...在实际应用中,一定要确保关联条件正确无误,避免不必要的数据更改,同时注意性能优化,减少全表扫描和提高查询效率。

    Oracle表连接方式

    这时候成本接近于全表扫描小表+分区数*全表扫描大表的代价和。至于两个表都进行分区,其好处是可以使用parallel query,就是多个进程同时对不同的分区进行join,然后再合并。但是复杂。使用hash join时,HASH_AREA_...

    Oracle大表分区的技术

    2. **避免跨分区操作**:设计应用程序时,尽量避免全表扫描和跨分区的JOIN操作。 3. **考虑分区边界**:合理设置分区边界,确保新数据能自动落入正确分区。 4. **利用分区修剪**:通过编写明智的SQL语句,让数据库...

    Oracle数据库整理表碎片

    当进行全表扫描时,Oracle会读取高水位下的所有数据块,即使这些数据块包含大量空闲空间(即碎片)。这种情况下,读取这些空闲数据块会显著降低全表扫描的性能。 此外,行链接和行迁移也会导致表碎片的产生。行链接...

    优化Oracle库表设计的若干方法

    其次,索引的选择应考虑全列扫描和部分列扫描的情况,避免过度索引导致写操作性能下降。此外,应考虑使用覆盖索引,即索引包含查询所需的所有列,以减少回表操作。 在实际操作中,使用数据库设计工具如...

    oracle索引类型及扫描方式大整理new

    B\*Tree索引特别适用于当所需检索的行数占总行数比例较低的情况,此时相比全表扫描,B\*Tree索引能提供更高效的检索方式。 B\*Tree索引的树结构中,叶块位于树的底部,包含被索引列的值及其对应的rowid。分支块则...

    Oracle 9i用索引跳跃扫描提高查询速度

    `,Oracle9i 也会使用索引跳跃式扫描,避免了对全表扫描的需求。 索引跳跃式扫描的工作原理是,Oracle 内部会分解查询,生成多个子查询,每个子查询针对索引的不同部分进行操作。例如,对于上述例子,Oracle 实际上...

    oracle优化规则总汇

    一般推荐使用COST或RULE,避免不必要的全表扫描。 2. **访问Table的方式**:有两种主要方式,全表扫描和通过ROWID访问。全表扫描适合小表,而ROWID访问通常更快,尤其是当有索引时。索引能提供ROWID的快速访问,...

Global site tag (gtag.js) - Google Analytics