Oracle面试题之SQL tunting
1:列举几种表连接方式
答:一共有三种连接方式(SQL优化),嵌套循环(Nested Loops(NL)),哈希连接,也叫散列连接(Hash Join(HJ)),排序合并连接,也叫归并连接(Sort Merge Join(SMJ))。
注:
Oracle一次只能连接两个表。不管查询中有多少个表,Oracle在连接中一次仅能操作两张表。当执行多个表的连接时,优化器从一个表开始,将它与另一个表连接;然后将中间结果与下一个表连接,以此类推,直到处理完所有表为止。
2:不借助第三方工具,怎样查看sql的执行计划
答:设置autotrace。或者使用SQL语句。(答题时请回答详细,加上解析)
解析:
如果要分析某条SQL的性能问题,通常我们要先看SQL的执行计划,看看SQL的每一步执行是否存在问题。如果一条SQL平时执行的好好的,却有一天突然性能很差,如果排除了系统资源和阻塞的原因,那么基本可以断定是执行计划出了问题。
一.查看执行计划的三种方法
1.1设置autotrace
1
SET AUTOTRACE OFF
此为默认值,即关闭Autotrace
2
SET AUTOTRACE ON EXPLAIN
只显示执行计划
3
SET AUTOTRACE ON STATISTICS
只显示执行的统计信息
4
SET AUTOTRACE ON
包含2,3两项内容
5
SET AUTOTRACE TRACEONLY
与ON相似,但不显示语句的执行结果
1.2使用SQL
SQL>EXPLAIN PLAN FOR sql语句;
SQL>SELECT plan_table_output FROMTABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
例如:
SQL> EXPLAIN PLAN FOR SELECT * FROM dba_users;
已解释。
SQL> SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));
1.3使用Toad,PL/SQL
Developer工具
3:如何使用CBO,CBO与RULE的区别
答:
在optimizer_mode=choose时,如果表有统计信息(分区表外),优化器将选择CBO,否则选RBO。RBO遵循简单的分级方法学,使用15种级别要点,当接收到查询,优化器将评估使用到的要点数目,然后选择最佳级别(最少的数量)的执行路径来运行查询。
CBO尝试找到最低成本的访问数据的方法,为了最大的吞吐量或最快的初始响应时间,计算使用不同的执行计划的成本,并选择成本最低的一个,关于表的数据内容的统计被用于确定执行计划。
解析:
Oracle的优化器有两种优化方式,即基于规则的优化方式(Rule-Based
Optimization,简称为RBO)和基于代价的优化方式(Cost-Based Optimization,简称为CBO),在Oracle8及以后的版本,Oracle强列推荐用CBO的方式。
RBO方式:优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。比如我们常见的,当一个where子句中的一列有索引时去走索引。
CBO方式:它是看语句的代价(Cost),这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息。统计信息给出表的大小、有多少行、每行的长度等信息。这些统计信息起初在库内是没有的,是做analyze后才出现的,很多的时侯过期统计信息会令优化器做出一个错误的执行计划,因此应及时更新这些信息。
注:
走索引不一定就是优的,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时全表扫描(full table scan)是最好。
优化模式包括Rule、Choose、First rows、All rows四种方式:
Rule:基于规则的方式。
Choolse:默认的情况下Oracle用的便是这种方式。指的是当一个表或或索引有统计信息,则走CBO的方式,如果表或索引没统计信息,表又不是特别的小,而且相应的列有索引时,那么就走索引,走RBO的方式。
First Rows:它与Choose方式是类似的,所不同的是当一个表有统计信息时,它将是以最快的方式返回查询的最先的几行,从总体上减少了响应时间。
All Rows:也就是我们所说的Cost的方式,当一个表有统计信息时,它将以最快的方式返回表的所有的行,从总体上提高查询的吞吐量。没有统计信息则走RBO的方式。
关于如何设定选择哪种优化器模式:
A、instant级别
修改初始化参数,我们可以通过在init.ora文件中设定OPTIMIZER_MODE=RULE、OPTIMIZER_MODE=CHOOSE、OPTIMIZER_MODE=FIRST_ROWS、OPTIMIZER_MODE=ALL_ROWS去选用3所提的四种方式,如果你没设定OPTIMIZER_MODE参数则默认用的是Choose这种方式。
B、session级别
当前会话输入altersession set optimizer_mode = xxx scope = both;
C、语句级别
通过HINT提示来选择
select /*+ rule*/e.ename,d.deptno from emp e ,dept d
where e.deptno = d.deptno
强调一点:你设置的hint所包含的执行计划一定要有否则这个hint就相当于comment
4:如何定位重要(消耗资源多)的SQL
答:
A、查看值得怀疑的SQL
select substr(to_char(s.pct,'99.00'),2)||'%'load, s.executions executes,
p.sql_text from(select address,disk_reads,executions,pct,
rank()over(order by disk_reads desc) ranking
from(select address,
disk_reads,
executions,
100*ratio_to_report(disk_reads)over() pct
from sys.v_$sql
where command_type!=47)
where disk_reads>50*executions) s,
sys.v_$sqltext p
where s.ranking<=5
and p.address=s.address
order by 1, s.address, p.piece;
B、查看消耗内存多的sql
select b.username,
a. buffer_gets,
a.executions,
a.disk_reads / decode(a.executions, 0, 1, a.executions),
a.sql_text SQL
from v$sqlarea a, dba_users b
where a.parsing_user_id = b.user_id
and a.disk_reads > 10000
order by disk_reads desc;
C、查看逻辑读多的SQL
select*
from(select buffer_gets, sql_text
from v$sqlarea
where buffer_gets>500000
order by buffer_gets desc)
where rownum<=30;
D、查看执行次数多的SQL
select sql_text, executions
from (select sql_text, executions from v$sqlarea order by executions desc)
where rownum < 81;
E、查看读硬盘多的SQL
select sql_text, disk_reads
from(select sql_text, disk_reads from v$sqlarea order by disk_reads desc)
where rownum<21;
F、查看排序多的SQL
select sql_text, sorts
from(select sql_text, sorts from v$sqlarea order by sorts desc)
where rownum<21;
G、分析的次数太多,执行的次数太少,要用绑变量的方法来写sql
select substr(sql_text, 1, 80) "sql", count(*), sum(executions) "totexecs"
from v$sqlarea
where executions < 5
group by substr(sql_text, 1, 80)
having count(*) > 30
order by 2;
5:如何跟踪某个session的SQL
答:
Oracle自带的sql trace程序可以跟踪本地session
sys: alter
system set sql_trace = true;对所有会话跟踪
schema:
alter session set sql_trace = true;对某个session会话跟踪sql语句
用tkprof来格式化跟踪文件输出
tkprof输出内容包括1 sql语句2统计信息3explain
table执行计划
6:SQL调整最关注的是什么
答:
调整的目的就是为了消耗最小的资源来完成功能,通过查看执行计划和各种统计信息来分辨调整后的sql对资源的耗费情况,来找出一个成本最小的sql语句
检查系统的I/O问题
vmstate能检查整个系统的iostat(IOstatistics
查看该SQL的responsetime(db block gets/consistent gets/physical reads/sorts (disk))
7:说说你对索引的认识(索引的结构、对dml影响、为什么提高查询性能)
答:
第一讲、索引并非总是最佳选择
1.表未做statistics,或者statistics陈旧,导致Oracle判断失误。
2.根据该表拥有的记录数和数据块数,实际上全表扫描要比索引扫描更快。
第二讲、索引也有好坏
1.索引不是越多越好。特别是大量从来或者几乎不用的索引,对系统只有损害。OLTP系统每表超过5个索引即会降低性能,而且在一个sql中,Oracle从不能使用超过5个索引。
2.很多时候,单列索引不如复合索引有效率。
3.用于多表连结的字段,加上索引会很有作用。
第三讲、索引再好,不用也是白搭
1. where子句中的这个字段,必须是复合索引的第一个字段。
2. where子句中的这个字段,不应该参与任何形式的计算。
具体来讲,假设一个索引是按f1, f2,
f3的次序建立的,现在有一个sql语句, where子句是f2 = : var2,则因为f2不是索引的第1个字段,无法使用该索引。
索引通常能提高select/update/delete的性能,会降低insert的速度。
8:使用索引查询一定能提高查询的性能吗?为什么?
答:
索引就是为了提高查询性能而存在的,如果在查询中索引没有提高性能,只能说是用错了索引,或者讲是场合不同。
9:绑定变量是什么?绑定变量有什么优缺点?
答:
绑定变量是相对文本变量来讲的,所谓文本变量是指在SQL直接书写查询条件,这样的SQL在不同条件下需要反复解析,绑定变量是指使用变量来代替直接书写条件,查询bind value在运行时传递,然后绑定执行。优点是减少硬解析,降低CPU的争用,节省shared_pool ;缺点是不能使用histogram,sql优化比较困难。
10:如何稳定(固定)执行计划
答:
程序代码query_rewrite_enabled= true
star_transformation_enabled= true
optimizer_features_enable= 9.2.0
创建并使用stored outline
oracle canautomatically create outlines for all SQL statements, or you can create themfor specific SQL statements. In either case, the outlines derive their inputfrom the optimizer.
oracle creates stored outlinesautomatically when you set the initialization parameter Create_STORED_OUTLINESto true. When activated, oracle creates outlines for all compiled SQLstatements. You can create stored outlines for specific statements using theCreate OUTLINE statement.
Creating
Outlines:
11:和排序相关的内存在8i和9i分别怎样调整,临时表空间的作用是什么
答:
Oracle 8i中sort_area_size/sort_area_retained_size决定了排序所需要的内存,如果排序操作不能在sort_area_size中完成,就会用到temp表空间
Oracle 9i中如果workarea_size_policy=auto时,排序在pga内进行,通常pga_aggregate_target的1/20可以用来进行disk
sort;如果workarea_size_policy=manual时,排序需要的内存由sort_area_size决定
在执行order by/group
by/distinct/union/create index/index rebuild/minus等操作时,如果在pga或sort_area_size中不能完成,排序将在临时表空间进行(disk
sort),临时表空间主要作用就是完成系统中的disk sort.
12:存在表T(a,b,c,d),要根据字段c排序后取第21—30条记录显示,请给出sql
答:
程序代码
create table t(a number(,b number(,cnumber(,d number();
/
Begin
for i in 1 .. 300 loop
insert into t values(mod(i,2),i/2,dbms_random.value(1,300),i/4);
end loop;
end;
/
select * from (select c.*,rownum as rn from(select * from t order by c desc) c) where rn between 21 and 30;
/
select * from (select * from test order byc desc) x where rownum < 30
minus
select * from (select * from test order byc desc) y where rownum < 20 order by 3 desc
相比之minus性能较差