oracle的SQL索引使用

Posted

tags:

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

oracle数据库:

1、select * from table where a=a and b=b and c=c and d=d;
这里我建立了一个a,b,c,d的复合索引,但如果使用:
select * from table where a=a and b=b;
进行查询时第一次很慢,第二次之后再查就快了,应该是使用了数据库的缓冲区进行的查询,那这个abcd的复合索引对于where a=a and b=b;就不起作用了么?如果有若干个SQL:
select * from table where a=a;
select * from table where a=a and b=b;
select * from table where a=a and b=b and c=c;
select * from table where a=a and b=b and c=c and d=d;
等等,总不能对每个where条件建立一个索引?

2、有没有SQL可以查询某个SQL执行时是否使用索引了?

谢谢!
where a=变量a;
where a=变量a and b=变量b;
where a=变量a and b=变量b and c=变量c;
where a=变量a and b=变量b and c=变量c and d=变量d;
这些都可以用abcd这个复合索引?
但从现在执行的时间来看,a=变量a这里是没有用到索引的,不知道有什么方法可以让它走索引么?

1,第一次查询慢,以后就快了,主要是因为第一次要进行磁盘操作,以后数据被cache到内存中了,不在操作磁盘,所以就快了。
2,对于你说的这四种查询,where条件中的a=a估计你是举例子这样写的吧。实际上应该是a=变量A。其他的b,c,d也是这样。那么这种语句都是可以利用你说的复合索引的。如果是RBO优化器,这四句都应该用索引。但是oracle现在推荐的CBO优化器不能保证你都走索引。
3,到底用没用索引,你可以从v$sqlaera中找到你的语句对应的hash_value,然后从v$sql_plan中找到语句的执行计划,通过执行计划确认你的语句是不是使用了索引。
具体语句你可以类似如下写法:

select hash_value,sql_text from v$sqlarea where upper(sql_text) like '%你需要查找的sql语句的特征片段%'

select * from v$sql_plan where hash_value = 上一句查到的hash_value
参考技术A 是不是利用了索引你可以看一下这个语句的查询计划,至于如何获取执行计划,查一下,很多的!假如真如你所说没有用到索引,可能是由于你的查询有话器配置参数有问题,或者统计信息已经过时,原因可能有很多,当然你可以使用很多的方法建议查询优化器使用索引,其中包括提示、存储提纲、sql计划基线等,如果还是不懂,去网上查吧,网络是个很好的学习环境。 参考技术B 方法如下:
Oracle中建立索引,会提高查询速度: create index 索引名 on 表名(列名);
例如:
create index index_userid on tbl_detail(userid);
如何找数据库表的主键字段的名称?
SELECT * FROM user_constraints WHERE CONSTRAINT_TYPE='P' and table_name='AAA'; select * from dba_cons_columns where CONSTRAINT_NAME='SYS_AAA';
Oracle 在创建主键(可以不加constraint SYS_AAA),会为库表自动创建索引,
索引的列为主键列。 并且当库表某些列名或者库表名改变时候,
Oracle自动创建的索引SYS_AAA,中的索引列也会自动更新(类似于视图),并且SYS_AAA会与名字更改后的库表还是保持索引关系。 关键系统库表: desc dba_constraints desc dba_cons_columns
desc dba_indexes desc dba_ind_columns desc DBA_TAB_COLUMNS
例子1:更改库表的列名
ALTER TABLE AAA RENAME COLUMN ID TO AAA_ID; create table AAA ( ID NUMBER(8), NAME CHAR(20),
constraint SYS_AAA primary key(ID) );
//查找约束名字
select c.CONSTRAINT_NAME,c.table_name,cc.COLUMN_NAME from user_constraints c, user_cons_columns cc
where c.constraint_name=cc.constraint_name and c.table_name ='AAA' AND C.CONSTRAINT_TYPE='P';
//查找索引
select index_name,index_type,uniqueness from user_indexes where table_name='AAA'; INDEX_NAME INDEX_TYPE UNIQUENES
参考技术C ....个人认为貌似和索引的关系不是很大.
因为,系统要解析新的SQL语句肯定要花时间的.
相关内容 我觉得可能要看下 Oracle DB 里面关于 硬解析和软解析的描述.

Oracle 建立索引及SQL优化

数据库索引:

索引有单列索引,复合索引之说,如果某表的某个字段有主键约束和唯一性约束,则Oracle 则会自动在相应的约束列上建议唯一索引。数据库索引主要进行提高访问速度。

建设原则:

 1、索引应该经常建在where 子句经常用到的列上。如果某个大表经常使用某个字段进行查询,并且检索行数小于总表行数的5%。则应该考虑。

 2、对于两表连接的字段,应该建立索引。如果经常在某表的一个字段进行order By 则也经过进行索引。

 3、不应该在小表上建设索引。

优缺点:
 1、索引主要进行提高数据的查询速度。 当进行DML时,会更新索引。因此索引越多,则DML越慢,其需要维护索引。 因此在创建索引及DML需要权衡。

创建索引:
 单一索引:

Create Index <Index-Name> On <Table_Name>(Column_Name);

 复合索引:

Create Index i_deptno_job on emp(deptno,job); —>在emp表的deptno、job列建立索引。

select * from emp where deptno=66 and job=sals ->走索引。

select * from emp where deptno=66 OR job=sals ->将进行全表扫描。不走索引

select * from emp where deptno=66 ->走索引。

select * from emp where job=sals ->进行全表扫描、不走索引。

如果在where 子句中有OR 操作符或单独引用Job 列(索引列的后面列) 则将不会走索引,将会进行全表扫描。

sql 优化:

当Oracle数据库拿到SQL语句时,其会根据查询优化器分析该语句,并根据分析结果生成查询执行计划。也就是说,数据库是执行的查询计划,而不是Sql语句。查询优化器有rule-based-optimizer(基于规则的查询优化器) 和Cost-Based-optimizer(基于成本的查询优化器)。其中基于规则的查询优化器在10g版本中消失。对于规则查询,其最后查询的是全表扫描。而CBO则会根据统计信息进行最后的选择。

1、先执行From ->Where ->Group By->Order By

2、执行From 字句是从右往左进行执行。因此必须选择记录条数最少的表放在右边。这是为什么呢?

3、对于Where字句其执行顺序是从后向前执行、因此可以过滤最大数量记录的条件必须写在Where子句的末尾,而对于多表之间的连接,则写在之前。因为这样进行连接时,可以去掉大多不重复的项。

4. SELECT子句中避免使用(*)ORACLE在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间

5、索引失效的情况:
 ① Not Null/Null 如果某列建立索引,当进行Select * from emp where depto is not null/is null。 则会是索引失效。

 ② 索引列上不要使用函数,SELECT Col FROM tbl WHERE substr(name ,1 ,3 ) = ‘ABC‘ 
或者SELECT Col FROM tbl WHERE name LIKE ‘%ABC%‘ 而SELECT Col FROM tbl WHERE name LIKE ‘ABC%‘ 会使用索引。

 ③ 索引列上不能进行计算SELECT Col FROM tbl WHERE col / 10 > 10 则会使索引失效,应该改成
SELECT Col FROM tbl WHERE col > 10 * 10

 ④ 索引列上不要使用NOT ( != 、 <> )如:SELECT Col FROM tbl WHERE col ! = 10 
应该 改成:SELECT Col FROM tbl WHERE col > 10 OR col < 10 。

6、用UNION替换OR(适用于索引列)

  union:是将两个查询的结果集进行追加在一起,它不会引起列的变化。 由于是追加操作,需要两个结果集的列数应该是相关的,并且相应列的数据类型也应该相当的。union 返回两个结果集,同时将两个结果集重复的项进行消除。如果不进行消除,用UNOIN ALL。

    通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果。 对索引列使用OR将造成全表扫描。注意, 以上规则只针对多个索引列有效。 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低。在下面的例子中, LOC_ID 和REGION上都建有索引。

高效:

SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”

低效:

SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”

如果你坚持要用OR,那就需要返回记录最少的索引列写在最前面。

7. 用EXISTS替代IN、用NOT EXISTS替代NOT IN

在许多基于基础表的查询中, 为了满足一个条件, 往往需要对另一个表进行联接. 在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中, NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下, NOT IN都是最低效的(因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN, 我们可以把它改写成外连接(Outer Joins)或NOT EXISTS。

例子:

高效: SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB‘)

低效: SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB‘)

本文转自:http://www.cnblogs.com/tianmingt/articles/4444885.html

以上是关于oracle的SQL索引使用的主要内容,如果未能解决你的问题,请参考以下文章

oracle删除某个表的索引的sql语句

如何在sql语句中显示Oracle索引

Oracle 建立索引及SQL优化

Oracle 建立索引及SQL优化

oracle如何才能让这样的SQL查询走索引,除了拼SQL还有别的方法吗?

oracle SQL查询,用大于等于不走索引,怎么解决