为什么要建立索引,几乎每个人的第一反应就是能够提升查询速度。但是建立索引和不建立索引有什么区别,索引为什么能够提升查询速度呢。
当数据库表中存在数据量比较大时,对表执行指定条件的查询的时候。常规的查询方法会将所有的记录都读取出来,然后再把读取的每一条记录与查询条件进行对比,最后返回满足条件的记录。这样进行操作的时间开销和I/O开销都很大。对于这种情况,就可以考虑通过建立索引来减小系统开销。
有了索引之后,只需要在索引中找到符合查询条件的索引字段值,就可以通过保存在索引中的ROWID快速找到表中对应的记录。举个例子索引就像是一本书的目录,通过目录可以迅速找到相应的页码,进而可以阅读相应页码的内容,而没必要去翻看整本书去一页一页的查找。
create or replace unique|bitmap index . on .
(| asc|desc ,
| asc|desc ...)
–eg:
create index index_sno on student('name');
其实上面这几个属性就差不多够用了,其他还有很多属性。
create or replace unique|bitmap index . on .
(| asc|desc ,
| asc|desc ...)
tablespace
storage
logging|nologging
compute statistics
nocompress|compress
nosort|reverse
partition|global partition
alter index [index_name1] rename to [index_name2];
表使用一段时间后在索引中会产生碎片,此时索引效率会降低,可以选择重建索引或者合并索引,合并索引方式更好些,无需额外存储空间,代价较低(涉及到索引的结构,细讲可以单独写篇博客了)。
alter index [index_name] coalesce;
alter index [index_name] rebuild;
drop index [index\_name];
select index_name, index_type, tablespace_name, uniqueness from all_indexes where table_name ='table_name';
create index index_sno on student('name');
select * from all_indexes where table_name='student';
以上原因对比一下索引的优缺点就会明白。
(默认索引,保存排序过的索引列和对应的rowid值)
create index index_sno on student('sno');
create bitmap index index_sno on student(sno);
注意:如果索引建立在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引,即至少要包含组合索引的第一列。(复合索引的顺序要求记不太清了,只记得要将最常查询的列放在最前面,后续补上)
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' ->进行全表扫描、不走索引。
create index fbi on student (upper(name));
select * from student where upper(name) ='WISH';
SELECT ... FROM emp WHERE comm IS NULL;
comm 列的索引会失效
如果没有使用基于函数的索引,那么 where 子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。例如:select * from staff where trunc(birthdate) = '01-MAY-82';
但是把函数应用在条件上,索引是可以生效的,把上面的语句改成下面的语句,就可以通过索引进行查找。select * from staff where birthdate < to_date('01-MAY-82');
注意:对于 MIN, MAX 函数,Oracle 仍然使用索引。
之前有看到说’T%'的话索引是会生效的,有待验证。
( 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中.)
不等于操作包括:<>, !=, NOT colum >= ?, NOT colum <= ?
对于这个限制条件可以通过 OR 替代,例如: colum <> 0 ===> colum>0 OR colum<0
SELECT emp_id, emp_m, salary_q ... FROM emp WHERE job='manager' AND dept_no>10;
job 和 dept_no 都是非唯一索引,这种条件下 oracle 不会合并索引,它只会使用第一个索引。
dept_no是一个varchar2型的字段,在这个字段上有索引,但是下面的语句会执行全表扫描。select * from dept where dept_no = 900198;
这是因为 oracle 会自动把 where 子句转换成 to_number(dept_no)=900198,相当于使用函数,这样就限制了索引的使用。
正确写法如下:select * from dept where dept_no = '900198';
这篇文章主要是对着以前做的笔记进行回忆和总结,现在工作中除了写写SQL基本上与Oracle数据库没太大关系了,感觉以前学的很多东西都快要忘记了。也包括markdown~||,为了写这边博客又特地复习了一下。由于博主的阅历有限,时间又有点晚了,写的可能有点仓促,文中不足和错误的地方欢迎大家指正^^,后续我会修改。文中还缺乏很多例子,后续有时间也会补上。
参考链接:
https://blog.csdn.net/sinat_27933301/article/details/79968971
https://blog.csdn.net/runrabbit/article/details/52151990
https://www.cnblogs.com/wishyouhappy/p/3681771.html
https://www.cnblogs.com/wang-junxi/archive/2017/12/25/8111663.html