oracle 数据索引为啥没有起到作用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle 数据索引为啥没有起到作用相关的知识,希望对你有一定的参考价值。

有一个表,字段有cdate,ndwbm,n1...n24。字段类型都是varchar2类型,我用cdate,ndwbm作为索引,数据行数在50万,查询速度是0.5s,而我把索引都改成upper(cdate),upper(ndwbm),where upper(cdate)='2012-01-01' and upper(ndwbm)='11102'这样查就0.04s。为什么会这样?

参考技术A 常规索引使用的时候不要带函数,带了函数之后就是全表扫。
后面那种是函数索引,写法也正好引用到了索引,自然会快。追问

我最终的查询不想用upper。where cdate='2012-01-01' and ndwbm='11102'想要这样的。

参考技术B upper已经完成了字符的处理了,直接建索引可能遇到了空值的问题了追问

Select * From table t
Where cdate is null or ndwbm is null
这样查,没有查出记录,说明没有空值吧。

只要建立索引的列里没有空值就行吧。

Oracle数据库如何提高访问性能

A,避免在索引列上使用 IS NULL 和 IS NOT NULL 操作

避免在索引中使用然后可以为空的列,ORACLE将无法使用该索引。对于单列索引  如果包含空值,索引将不存在此记录。对于复合索引 如果每个列都为空,索引中同样不存在此记录。如果至少有一个列不为空则记录存在于索引中

B, 用 UNION 替换 OR (适用于索引列)

通常情况下,用UNION替换where子句中的OR会起到较好的作用。对索引列使用OR会造成全表扫描。(以上规则只针对多个索引列有效,如果column没有被索引,查询效率可能会因为没有用OR而降低)

C, 分离表和索引

总是将你的表和索引建立在不同的表空间内(TABLESPACES).决不要将不属于ORACLE内部系统的对象存放到SYSTEM表空间里。同时,确保数据表空间和索引表空间于不同的硬盘上(通过指定表空间的方式可以实现这个要求)

D ,共享SQL语句

为了不重复解析相同的SQL语句,在第一次解析之后,ORACLE将SQL语句存放在内存中,这块位于系统全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享,因此,当你执行一个SQL语句(有时被称为个游标)时,如果它和之前的执行过的语句完全相同,ORACLE就能很快获得已经被解析的语句以及最好的执行路径。ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用。当你向ORACLE提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句.这里需要注明的是,ORACLE对两者采取的是一“种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,换行等)

E,WHERE子句连接顺序

WHERE子句中的连接顺序,
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数让记录的条件必须写在WHERE子句的末尾

F,SELECT 子句避免使用 *

当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 * 是一个方便的方法。 但,不幸的是 这是一个非常低效的方法.实际上,ORACLE在解析的过程中,会将*依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时

G,使用DECODE函数来减少处理时间

使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表,

例如:

SELECT COUNT(*),SUM(SAL)
FROM EMP
WHERE DEPT_NO= 0020
AND ENAME LIKE ‘SMITH%‘;


SELECT COUNT(*),SUM(SAL)
FROM EMP
WHERE DEPT NO = 0030
AND ENAME UKE ‘SMITH%‘;


你可以用DECODE函数高效地得到相同结果
SELECT COUNT(DECODE(DEPT NO,0020,‘X‘,NULL)) D0020_ COUNT,COUNT(DECODE(DEPT NO,0030,‘X‘,NULL)) D0030_ COUNT,SUM(DECODE(DEPT NO,0020,SAL,NULL) D0020_ SAL,SUM(DECODE(DEPT_NO,0030,SAL,NULL) D0030_ SAL FROM EMP WHERE ENAME LIKE ‘SMITH%‘;
类似的,DECODE函数也可以运用于GROUP BY和ORDER BY子句中。

H,用TRUNCATE替代DELETE

当删除表中的记录时,在通常情况下,回滚段(rollback segments)用来存放可以被恢复的信息。如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)而当运用TRUNCATE时,回滚段不再存放任何可被恢复的信息,当命令运行后,数据不能被恢复因此很少的资源被调用,执行时间也会很短。

(注意: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)

I,尽量多使用COMMIT

只要有可能,在程序中尽量多使用COMMIT,这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:COMMIT所释放的资源:

a.回滚段上用于恢复数据的信息,

b.被程序语句获得的锁

C. redo log buffer中的空间

d. ORACLE为管理上述3种资源中的内部花费
(注意:在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼)

J,WHERE子句替换HAVING子句

避免使用HAVING子句,HAVING只会在检索出所有记录之后才对结果集进行过滤.这个处理需要排序,总计等操作.如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。

K,用EXISTS替换IN

在许多基于基础表的查询中,为了满足一个条件,往往 需要对另 一个表进行联接 在这种情况下,使用EXISTS(或NOT EXISTS)通常将提高查询的效率

L,用NOT EXISTS替代NOT IN

在子查询中,NOT IN子句将执行一一个内部的排序和合并无论在哪种情况下,NOT IN都是最低效的(因为它对子查询中的表执行了一个全表遍历).为了避免使用NOT IN,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS

 













以上是关于oracle 数据索引为啥没有起到作用的主要内容,如果未能解决你的问题,请参考以下文章

Oracle数据库如何提高访问性能

为啥查询不使用Oracle中的索引

oracle 唯一约束 为啥 唯一索引

在oracle数据库中普通索引和唯一索引,请问哪个效率更高?

在Oracle中定义SQL查询。索引为啥不能直接从select语句中引用?求教,谢谢

oracle中,索引是干啥用的?