索引及SQL优化

一、索引

1.说明:

  • 索引是数据库对象之一,用于加快数据的检索,类似于书籍的索引。在数据库中索引可以减少数据库程序查询结果时需要读取的数据量,类似于在书籍中我们利用索引可以不用翻阅整本书即可找到想要的信息。
  • 索引是建立在表上的可选对象;索引的关键在于通过一组排序后的索引键来取代默认的全表扫描检索方式,从而提高检索效率
  • 索引在逻辑上和物理上都与相关的表和数据无关,当创建或者删除一个索引时,不会影响基本的表;
  • 索引一旦建立,在表上进行DML操作时(例如在执行插入、修改或者删除相关操作时),oracle会自动管理索引,索引删除,不会对表产生影响
  • 索引对用户是透明的,无论表上是否有索引,sql语句的用法不变
  • oracle创建主键时会自动在该列上创建索引

2.原理:

  • 若没有索引,搜索某个记录时(例如查找name=‘A’)需要搜索所有的记录,因为不能保证只有一个A,必须全部搜索一遍
  • 若在name上建立索引,oracle会对全表进行一次搜索,将每条记录的name值升序排列,然后构建索引条目(name和rowid),存储到索引段中,查询name为wish时即可直接查找对应地方
  • 创建了索引并不一定就会使用,oracle自动统计表的信息后,决定是否使用索引,表中数据很少时使用全表扫描速度已经很快,没有必要使用索引

3.创建修改及查看:

创建索引

CREATE [UNIQUE] | [BITMAP] INDEX index_name  --unique表示唯一索引
ON table_name([column1 [ASC|DESC],column2    --bitmap,创建位图索引
[ASC|DESC],] | [express])
[TABLESPACE tablespace_name]
[PCTFREE n1]  --指定索引在数据块中空闲空间
[STORAGE (INITIAL n2)]
[NOLOGGING]   --表示创建和重建索引时允许对表做DML操作,默认情况下不应该使用
[NOLINE]
[NOSORT];     --表示创建索引时不进行排序,默认不使用

重命名索引

alter index 索引名 rename to 新索引名;

合并索引

表使用一段时间后在索引中会产生碎片,此时索引效率会降低,可以选择重建索引或者合并索引,合并索引方式更好些,无需额外存储空间,代价较低

alter index 索引名 coalesce;

重建索引

alter index 索引名 rebuild;

删除索引

drop index 索引名;

查看索引

select index_name,index-type, tablespace_name, uniqueness from all_indexes where table_name ='表名';

使用强制索引

使用强制索引,在SELECT 后面加上/*…*/ 中间加上索引的属性,代码如下:

SELECT /*+index(t pk_emp)*/* FROM EMP T   
--强制索引,/*.....*/第一个星号后不能有空格,里边内容结构为:加号index(表名 空格 索引名)。
--如果表用了别名,注释里的表也要使用别名。

4.分类:

①B-tree索引

  • B-tree索引是oracle中最常用的索引;B树索引类似二叉树;叶子节点(双向链表)包含索引列和指向表中每个匹配行的ROWID值
  • 所有叶子节点具有相同的深度,因而不管查询条件怎样,查询速度基本相同
  • 能够适应精确查询、模糊查询和比较查询
  • 分类:UNIQUE,NON-UNIQUE(默认),REVERSE KEY(数据列中的数据是反向存储的)
  • 创建例子:
craete  index index_sno on student('sno');
  • 适合使用场景:列基数(列不重复值的个数)大时适合使用B-tree索引

②位图索引

  • 创建位图索引时,oracle会扫描整张表,并为索引列的每个取值建立一个位图(位图中,对表中每一行 使用一位(bit,0或者1)来标识该行是否包含该位图的索引列的取值,如果为1,表示对应的rowid所在的记录包含该位图索引列值),最后通过位图索 引中的映射函数完成位到行的ROWID的转换
  • 创建例子
    create bitmap index index_sno on student(sno);
  • 适合场景:
    对于基数小的列适合简历位图索引(例如性别等)

③单列索引和复合索引(基于多个列创建)

即如果索引建立在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引,即至少要包含组合索引的第一列

④函数索引

  • 说明:
      1. 当经常要访问一些函数或者表达式时,可以将其存储在索引中,这样下次访问时,该值已经计算出来了,可以加快查询速度
      2. 函数索引既可以使用B数索引,也可以使用位图索引;当函数结果不确定时采用B树索引,结果是固定的某几个值时使用位图索引
      3. 函数索引中可以水泥用len、trim、substr、upper(每行返回独立结果),不能使用如sum、max、min、avg等
  • 例子:
    create index_st on student (upper(name));

5.索引建立原则总结

  1. 如果有两个或者以上的索引,其中有一个唯一性索引,而其他是非唯一,这种情况下oracle将使用唯一性索引而完全忽略非唯一性索引
  2. 至少要包含组合索引的第一列(即如果索引建立在多个列上,只有它的第一个列被where子句引用时,优化器才会使用该索引)
  3. 小表不要建立索引
  4. 对于基数大的列适合建立B树索引,对于基数小的列适合建立位图索引
  5. 列中有很多空值,但经常查询该列上非空记录时应该建立索引
  6. 经常进行连接查询的列应该创建索引
  7. 使用create index时要将最常查询的列放在最前面
  8. LONG(可变长字符串数据,最长2G)和LONG RAW(可变长二进制数据,最长2G)列不能创建索引
    9.限制表中索引的数量(创建索引耗费时间,并且随数据量的增大而增大;索引会占用物理空间;当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度)

二、SQL优化

1.记录条数较多的表放在靠近from的位置

ORACLE 的解析器按照从右到左的顺序处理 FROM 子句中的表名,因此 FROM 子句中写在最后的表(基础表 driving table)将被最先处理。在FROM 子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。

2.过滤较多记录的条件放在where子句末尾

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

3.先过滤后表关联

在进行多表关联时,多用 Where 语句把单个表的结果集最小化,多用聚合函数汇总结果集后再与其它表做关联,以使结果集数据量最小化。

4.减少对表的全表扫描

在含有子查询的 SQL语句中,要特别注意减少对表的查询

5.用EXISTS替代IN

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接。在这种情况下,使用 EXISTS(或 NOT EXISTS)通常将提高查询的效率。使用 exists 而不用 IN 因为 Exists 只检查行的存在,而 in 检查实际值。

6.避免在SELECT 子句中使用 DISTINCT

7.避免在索引列上使用计算、函数

应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。

8.用>=替代>

9.避免使用like操作符

遇到需要用到 LIKE 过滤的SQL语句,完全可以用 instr 代替。处理速度将显著提高

10.优先使用where过滤

提高 GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY之前过滤掉。而不是使用having过滤。

11.避免改变索引列的类型

12.避免空值判断

应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

13.避免在 where 子句中使用 or、in 和 not in

应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描, in 和 not in 也要慎用,否则会导致全表扫描。

14.至少使用复合索引第一字段

在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

15.不要使用星号

任何地方都不要使用 select * from ,要用具体的字段代替星号。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

韦陀无情花有意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值