您的位置:首页 > 数据库

数据库优化之SQL优化

2018-04-02 16:13 141 查看
1.创建索引

索引可以帮助查询速度更快,但是不正确的where也会导致索引失效而采用全文收索,因此注意一下几点:

⑴、不能用null作索引,任何包含null值的列都将不会被包含在索引中,任何在where语句中使用is null 或者 is not null的字段索引都会失效

⑵、尽量不要对索引列进行拼接,系统优化器对进行了拼接的字段将不会使用索引,列如字段A创建了索引,where B||A='as' 则A的索引会失效

⑶、尽量不要使用通配符或者以通配符开头,通配符“%”会大大的降低查询效率,当以通配符开头时,该字段索引失效

⑷、进行order by的字段最好都有索引,不要使用公式

⑸、索引列不要使用NOT 或者<> 或者!=,可以更改为< and >

⑹、避免对索引列进行计算
⑺、避免改变索引列的类型,例如字段A是数字,结果在where中和字符串进行比较

2.表名排序

oracle的解析顺序是从右到左,所以要将数据量最少的作为基表,将数据量最大的放到最后

3.where子句中的顺序

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

4.select 中最好不要使用* 改为具体要显示的列

在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间 

5.减少数据库的访问次数:每一次数据库的访问都会进行一系列的操作,解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等

6.设置Arraysize

Arraysize是sql*plus中可以设置的一个参数,这个参数设置的意思表示,sql*plus一次可以从数据库服务器端获取的记录行数。,一般默认是15,设置为200就可以了

7.使用DECODE,类似与if\else\then 或者case when,个人使用的比较少
使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。

8.如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)。个人的理解是减少数据库的访问次数

9. 尽量多使用COMMIT:只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少: 
COMMIT所释放的资源: 
a. 回滚段上用于恢复数据的信息. 
b. 被程序语句获得的锁 
c. redo log buffer 中的空间 
d. ORACLE为管理上述3种资源中的内部花费

10.用Where子句替换HAVING子句

避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后

11.使用表的别名(Alias): 

当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.

12.用exists替换in

eg: select A.* from A where A.id in(select B.id from B where B.id =A.id)

替换:select A.* from A where exists (select B.* from B where A.id=B.id)

13.用not exists 替换 not in

exists:取两表交集

not exists:取两表差集,第一个表中不包含第二个表中数据的数据

注意:exists后面可以是整句查询,子查询不允许有compute子句和into关键字,并且可以返回NULL值

14.避免视图的联合查询

15.识别‘低效执行’的SQL语句:

虽然目前各种关于SQL优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法: 

SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;

索引是表的一个概念部分,用来提高检索数据的效率,Oracle使用了一个复杂的自平衡B-tree结构。通常,通过索引查询数据比全表扫描要快。当 Oracle找出执行查询和Update语句的最佳路径时, Oracle优化器将使用索引。同样在联结多个表时使用索引也可以提高效率。另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列。通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率。虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价。索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改。这意味着每条记录的INSERT,DELETE , UPDATE将为此多付出4、 5次的磁盘I/O 。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢。定期的重构索引是有必要的:

ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>

select buffer_gets,executions,sql_tex from v$sqlarea.
16.用EXISTS替换DISTINCT

eg:SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO

替换:SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO)

17.SQL语句用大写的;因为Oracle总是先解析SQL语句,把小写的字母转换成大写的再执行

18.用>=替换>,用<=替换<

19.like通配符最好使用单边

20.用UNION替换OR (适用于索引列):

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

替换:SELECT LOC_ID 。 LOC_DESC ,REGION FROM LOCATION WHERE LOC_ID = 10 UNION SELECT LOC_ID ,LOC_DESC ,REGION FROM LOCATION WHERE REGION = “MELBOURNE” 

21.索引列放在where的最前面
22.用UNION-ALL 替换UNION :

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息