EXPLAIN PLAN FOR select * from INO_OUTAGES.OUTAGE where SUBCATEGORY=’NBN Outage’; SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
explain plan for select * from INO_SCHEDULING.IS_COMMANDS; select * from table(dbms_xplan.display);
EXPLAIN PLAN FOR select * from INO_OUTAGES.OUTAGE;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));EXPLAIN PLAN FOR select ID from INO_OUTAGES.OUTAGE;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
检索所有列时数据库会进行全表扫描
只检索索引列时, 只扫描索引表
如果是既查询索引列,又有额外的非索引列, 实际上也会进行全表扫描
EXPLAIN PLAN FOR select ID,DURATION,DESCRIPTION from INO_OUTAGES.OUTAGE;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
接下来看看谓词的情况
EXPLAIN PLAN FOR select * from INO_OUTAGES.OUTAGE where id=2146;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
当KEY, AREA_KEY, MANDATOR_KEY为联合索引,你尝试select这三列时,会得到一个INDEX FAST FULL SCAN
区别在于
索引快速全扫描的执行结果不一定是有序的。这是因为索引快速全扫描时Oracle是根据索引行在磁盘上的物理存储顺序来扫描,而不是根据索引行的逻辑顺序来扫描的,所以扫描结果才不一定有序, INDEX FAST FULL SCAN的性能要大大优于INDEX FULL SCAN
EXPLAIN PLAN FOR select KEY, AREA_KEY, MANDATOR_KEY from INO_ONCONFIG.LOOKUP_OPTIONS;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
谓词方面复杂一些
第一个例子, 如果不使用联合索引中全部的3个列,会得到一个全表扫描
EXPLAIN PLAN FOR select * from INO_ONCONFIG.LOOKUP_OPTIONS where AREA_KEY=’IFMS_SYMPTOM_CODE’ and MANDATOR_KEY=’PLATFORM’;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
第二个例子, 如果使用全部的三个索引列做谓词,会得到一个索引表扫描
EXPLAIN PLAN FOR select * from INO_ONCONFIG.LOOKUP_OPTIONS where KEY >’1′ and AREA_KEY=’INVOICE_INTERVALS’ and MANDATOR_KEY=’PLATFORM’;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
上面这个例子如果连select列都为索引列的话你甚至可以只使用索引表,不用查询主表
EXPLAIN PLAN FOR select AREA_KEY,MANDATOR_KEY from INO_ONCONFIG.LOOKUP_OPTIONS where KEY >’1′ and AREA_KEY=’INVOICE_INTERVALS’ and MANDATOR_KEY=’PLATFORM’;SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
4 加了索引之后的坏处是什么
增加了存储空间和插入及修改数据时造成的索引维护
5 哪些情况下没有索引反而要比有索引更快
这里有一种极端情况就是数据库所使用的硬盘随机读操作比较慢,而连续读比较快
假设谓词是 id in (1,10,13,45,234,676,233,234,67,89), 整个表的容量是100M
ALTER TABLE INO_ONCONFIG.LOOKUP_OPTIONS PARALLEL 4;
要关闭的话使用直接NOPARALLEL参数或者直接设置线程数为1好像也可以
ALTER TABLE INO_ONCONFIG.LOOKUP_OPTIONS NOPARALLEL;
ALTER TABLE INO_ONCONFIG.LOOKUP_OPTIONS PARALLEL 1;
2. 使用hint
需要注意的是如果需要指定schema名的话hint的时候需要把schema名去掉
select /*+ parallel(LOOKUP_OPTIONS 8) */ count(*) from INO_ONCONFIG.LOOKUP_OPTIONS;
下面我使用一个关联查询的sql来看看并行与非并行的区别
(我这里并发的消耗要比直接全表扫描join更大)
EXPLAIN PLAN FOR select * from INO_OUTAGES.OUTAGE o join INO_OUTAGES.BASE_LOOKUP b on o.id=b.OUTAGE_ID; SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));EXPLAIN PLAN FOR select /*+ parallel(o 4) */ /*+ parallel(b 4) */ * from INO_OUTAGES.OUTAGE o join INO_OUTAGES.BASE_LOOKUP b on o.id=b.OUTAGE_ID; SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));
PX 进程: Parallel Execution Slaves
Parallel to Serial(P->S): 并发到串行
Parallel to Parallel(P->P):并发到并发
Parallel Combined with parent(PCWP): 同一个从属进程执行的并行操作,同时父操作也是并行的。
Parallel Combined with Child(PCWC): 同一个从属进程执行的并行操作,子操作也是并行的。
EXPLAIN PLAN FOR select /*+ parallel(o 4) */ /*+ parallel(b 4) */ o.id,b.OUTAGE_ID,o.OUTAGE_TYPE from INO_OUTAGES.OUTAGE o left join INO_OUTAGES.BASE_LOOKUP b on o.id=b.OUTAGE_ID union all select /*+ parallel(o 4) */ /*+ parallel(h 4) */ h.id,h.OUTAGE_ID,o.OUTAGE_TYPE from INO_OUTAGES.OUTAGE o left join INO_OUTAGES.HISTORY h on o.id=h.OUTAGE_ID ; SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY(‘PLAN_TABLE’));