sql 避坑
1、表尽量使用别名,字段尽量使用别名.字段名,这样子,可以减少oracle数据库解析字段名。而且把不需要的字段名剔除掉,只保留有用的字段名,不要一直使用 select *。
2、关联查询时,选择好主表。oracle解析器对from 后面的表的解析是从右到左的,所以把数据量较小的表作为主表,然后和其他表进行关联,假如存在三个以下表,把同时交叉关联的表作为主表,提高查询效率。
3、where 条件后面的的条件解析是从下向上,从后先前解析执行的,所以可以把过滤数据量较多的条件放在最后面。
4、多利用表中数据行的rowid,rowid代表着表中数据存在的物理地址。例如删除重复记录的时候,可以根据rowid进行删除。
5、减少对表的查询,特别在子查询中,能尽量少重复访问表,就减少。
6、避免使用耗资源的操作,如distinct、Union、minus等这种需要全表查询的操作。
7、优化分组group by ,对group by字段要进行添加锁引,如果分组当中含有查询条件,要改写为where条件进行过滤后,再进行分组,而不是直接进行 having 条件。
8、用EXISTS替代IN、用NOT EXISTS替代 NOT IN,因为 not in是低效的,它必须对该字段的全部数据进行排序。
9、要合理利用索引字段提高查询效率。特别是常用的关联字段可以增加索引,主键、或者某些唯一字段。
10、利用>=替代>,因为>=可以直接定位到=的位置,而大于必须先定位位置,然后再查询下一个数据。耗时不一样。
11、关于用exists和in、not exists和inot in使用问题
IN适合于外表大而内表小的情况;exists适合于外表小而内表大的情况。
其中:NOT IN子句将执行一个内部的排序和合并,对子查询中的表执行一个全表遍历,因此是非常低效的。
12、Union 和Union all用法
Union:对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序。
Union All:对两个结果集进行并集操作,包括重复行,不进行排序。
13、使用DECODE函数来减少处理时间:
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
14、整合简单无关联的数据库访问
如果有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系),以减少多于的数据库IO开销。
虽然采取这种方法,效率得到提高,但是程序的可读性大大降低,所以还是要权衡之间的利弊。
15.使用where而非having
where语句是在group by 语句之前筛选出记录,而having是在各种记录都筛选之后再进行过滤,也就是说having子句是在数据库中提取数据之后再筛选。因此尽量在筛选之前将数据使用where子句进行过滤,因此执行的顺序应该如下
1使用where子句查找符合条件的数据
2使用group by子句对数据进行分组
3在group by分组的基础上运行聚合函数计算每一组的值
16.尽量少用连接符“+”连接字符串!
17.避免在索引列上使用NOT、<>、!= 通常,
18.避免在索引列上使用计算.
WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描.
19.避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.
20.分离表和索引
总是将你的表和索引建立在不同的表空间内(TABLESPACES)。
决不要将不属于ORACLE内部系统的对象存放到SYSTEM表空间里。
确保数据表空间和索引表空间置于不同的硬盘上
21.最后一个一定要学会查看执行计划,查看相关查询条件是否进入索引,找出问题所在,定位问题。
索引失效场景
- 没有 WHERE 子句
- 使用 IS NULL 和 IS NOT NULL
- WHERE 子句中使用函数
select * from staff where trunc(birthdate) = '01-MAY-82';
- 使用 LIKE ‘%T’ 进行模糊查询
--'123%' 会用到索引 select * from student where name like 'aaa%' ;
--'%123' 或者 '123' 不会使用索引 select * from student where name like '%123' ;
- WHERE 子句中使用不等于操作
- 等于和范围索引不会被合并使用
SELECT * FROM emp WHERE job='manager' AND deptno>10
- 比较不匹配数据类型
id是一个varchar2型的字段,在这个字段上有索引,但是下面的语句会执行全表扫描
select * from temp where id = 100101;
8.复合索引,不是使用的第一部分
--会用到索引 select * from student where name = '123'
--不会使用索引 select * from student where age = 18
9. or语句其中一个条件没有使用索引
alter table student add index my_index(name)
--由于age并没有创建索引,因此该语句索引失效
select * from student where name = '张三' or age = 18
版权归原作者 qq_19972217 所有, 如有侵权,请联系我们删除。