菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
474
0

SQL优化

原创
05/13 14:22
阅读数 14702

SQL优化的各种误区

1.对讹传辨知

  a)COUNT(*)与COUNT(列)

    - COUNT(*)针对全表,COUNT(列)针对列,两者不等价,无法比较其快慢。

      - 对于COUNT(列),优化器的算法是根据列的偏移量决定性能,列越靠后,访问的开销越大。COUNT(*)与偏移量无关,所以COUNT(*)最快,COUNT(最后列)最慢。

  b)SQL编写顺序

     - 表的查询顺序(针对多表查询):Oracle的解析器从右到左的顺序处理From子句中的表名,因此From子句中卸载最后的表(基础表)将被最先处理。在From子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表

    - where子句中的连接顺序:Oracle采用自下而上的顺序解析Where子句,根据这个原理,当在where子句中有多个表连接时,where子句中排在最后的表应当是返回行数可能最少的表,有过滤条件的子句应放在where子句中的最后。

     - 以上两种优化说法,基于RBO(Rule规则)确实如此。但是现在已是基于CBO(Cost代价),这些已经过时。

 

  c)IN与EXISTS

    - 一般来说,anti的反连接算法比filter更高效,但是在10g时,Oracle的这个算法不完善,必须要指定非空,才可以让not in用anti算法。在11g的时候,这个情况已经改变了,无论是not in 还是not exists,无论列是否为空,都可以走到Oracle比较先进高效的anti反连接算法。

 

2.少做事

  a)全局临时表

    -构建基于Session的全局临时表(global temporary table t_name on commit preserve rows):退出session该表记录会自动清空

    -构建基于事务的全局临时表(global temporary table t_name on commit delete rows):commit提交后,不等退出session,该表记录就会自动清空

  b)分区表(create table t_name (columns...) partition by range(column)(partition p1 values...))

    

  c)递归函数调用

    - 避免SQL中的函数调用,可以减少消耗

    - 减少SQL中的函数调用,函数调用不要放在结果集中

  d)集合写法

  e)只取所需的列

    - 只选择需要的列,而不用*。访问视图会变更快、表连接访问提速、索引不需要回表。

  

3.根据场景选择技术

  a)系统是个人用还是大家用?当前是忙还是闲?

 

  b)系统是多读还是少读?访问量是多还是少?

    - 索引的坏处:更新插入,因为索引性能会差;建索引引发锁表导致问题;建索引导致排序性能问题

    - 缓存结果集

    - 物化视图

    - 位图索引

    - Block如何设计

  c)先看表是大还是小?返回记录是多还是少?

    - 分区也会慢

    - 绑定变量居然引发故障

 

4.考虑需求最小化

  a)复杂的需求抽象简单化

  b)需求有没有多余

    - 需要去重吗

    - 需要排序吗

    - 需要监控吗

 

5.SQL改造等价性

  a)看似等价,其实不等价

    - insert all

insert all
    into tmp_transaction
    into tmp_session
select * from dba_objects;

不等价于

insert into tmp_transaction as select * from dba_objects;
insert into tmp_session as select * from dba_objects;

 

    

    - select max(), min()

select min(object_id), max(object_id) from t;
不等价于
select max(object_id) from t;
select min(object_id) from t;


select min(object_id), max(object_id) from t;
等价于
select max,min from (select max(object_id) max from t) a,
(select min(object_id) min from t) b;

 

    - in与><范围

    - count(*)与count(列)

 

  b)看似不等价,其实等价

 

    -关于表是否有记录的判断

 

 

6.需求是顶级优化(需求优化)

  a)需求优化需要不断的考虑

    - 界面权限设计优化(并非所有操作都需要做权限判定)

    - 界面实时刷新改良(先显示汇总,再由用户点击展示)

    - 单脚本对应多指示(不但多采集,还要去屏蔽规则)

    - 表单展示的异步载入(界面内容自上而下逐步展现)

 

  b)如下问答解决了很多性能问题

    - 排序有必有吗

    - 历史数据要保留多久

    - 这个需求过时了吗

    - 采集频率真要如此频繁吗

 

7.发现问题方法论

  a)先判断后动手

    - 故障未解决:备份相关证据、收集日志;分析主要矛盾,解决问题

    - 故障已消除:分析系统的日志,了解故障的时段

  b)先动态后静态

  c)先整体后局部

 


 

未完,待续。。。。。

 

发表评论

0/200
474 点赞
0 评论
收藏