Oracle——常用优化原则

一、什么是索引

百度百科: 在oracle索引是一种供服务器在表中快速查找一个行的数据库结构。合理使用索引能够大大提高数据库的运行效率。

个人解读:
1、索引是与表相关的一个可选结构,表中可以存在索引,也可以不存在索引。
2、在逻辑上和物理上都独立于表,索引和表可以存放在不同的表空间下面(逻辑上分离),可以存放在不同的磁盘下面(物理上分离)。
3、索引用于快速查找表的内容,可以提高SQL性能。

二、索引的类型

B-Tree索引(平衡树索引)

B-Tree索引适合于数据重复低的字段,常用于主键 唯一约束

Bitmap索引(位图索引)

适用于列的基数很少、数据重复多、更新少的

text索引(全文索引)

当字段里存储的都是文本时适合用全文索引,常用于搜索文字

三、索引的创建

1、唯一索引:键值不重复

CREATE UNIQUE INDEX index_name ON table_name (column_name)

2、一般索引:键值可重复

CREATE INDEX index_name ON table_name (column_name)

3、复合索引:绑定了多个列

CREATE INDEX index_name ON table_name (column_name1,column_name2)

四、数据库优化

1、SQL使用索引的例子

INDEX_COLUMN = ?
INDEX_COLUMN > ?
INDEX_COLUMN >= ?
INDEX_COLUMN < ?
INDEX_COLUMN <= ?
INDEX_COLUMN between ? and ?
INDEX_COLUMN in (?,?,...,?)
INDEX_COLUMN like ?||'%'(后导模糊查询)
T1. INDEX_COLUMN=T2. COLUMN1(两个表通过索引字段关联)

2、SQL不使用索引的例子

//不等于操作不能使用索引
INDEX_COLUMN <> ?
INDEX_COLUMN not in (?,?,...,?)

//经过普通运算或函数运算后的索引字段不能使用索引
function(INDEX_COLUMN) = ?
INDEX_COLUMN + 1 = ?
INDEX_COLUMN || 'a' = ?

//含前导模糊查询的Like语法不能使用索引
INDEX_COLUMN like '%'||?
INDEX_COLUMN like '%'||?||'%'

//B-TREE索引里不保存字段为NULL值记录,因此IS NULL不能使用索引
INDEX_COLUMN is null

//Oracle在做数值比较时需要将两边的数据转换成同一种数据类型,如果两边数据类型不同时会对字段值隐式转换,相当于加了一层函数处理,所以不能使用索引。
NUMBER_INDEX_COLUMN='12345'
CHAR_INDEX_COLUMN=12345
a.INDEX_COLUMN=a.COLUMN_1

3、常用优化方法

注意where字句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.
尤其是“主键ID=?”这样的条件。

SELECT子句中避免使用 ‘ * ‘
ORCLE在解释的过程中,会将*依次转换为所有的列名,这个工作是通过查询数据字典来完成的, 这意味着将耗费更多的时间。

避免在索引列上使用NOT
我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描。

避免在索引列上使用计算
WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描。

避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以为空的列,ORACLE性能上将无法使用该索引。对於单列索引,如果列包含空值,索引中将不存在此记录。对于复合索引,如果每个列都为空,索引中同样不存在此记录。

注意通配符%的影响
含前导模糊查询的Like语法不能使用索引,如:
INDEX_COLUMN like ‘%’||?
后导模糊查询的Like语法可以使用索引,如:
INDEX_COLUMN like ?||’%’

避免改变索引列的类型
Oracle在做数值比较时需要将两边的数据转换成同一种数据类型,如果两边数据类型不同时会对字段值隐式转换,相当于加了一层函数处理,导致不能使用索引。

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

用UNION-ALL 替换UNION ( 如果有可能的话)
当 SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序。 如果用UNION ALL替代UNION, 这样排序就不是必要了, 效率就会因此得到提高。 需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录。

Exists替换DISTINCT
带有DISTINCT,UNION,MINUS,INTERSECT的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能。DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序。 通常, 带有UNION,MINUS ,INTERSECT的SQL语句都可以用其他方式重写。

合理的使用Exists和In
EXISTS:首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间。
IN子查询时:首先系统先将主查询挂起,然后执行子查询,并将获得的结果列表存放在一个加了索引的临时表中。待子查询执行完毕,再执行主查询。这也就是使用EXISTS比使用IN通常查询速度快的原因。

1) select * from T1 where exists(select t1.id from T2 where T1.id=T2.id) ;
2) select * from T1 where T1.id in (select T2.id from T2) ;

T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高。
T1数据量非常大而T2数据量小时,T1>>T2 时,2) 的查询效率高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章