我已经为我的一个查询生成了一个解释计划。完整的解释计划如下所示
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 202 | 441 (2)| 00:00:06 |
| 1 | NESTED LOOPS OUTER | | 1 | 202 | 441 (2)| 00:00:06 |
| 2 | NESTED LOOPS OUTER | | 1 | 192 | 441 (2)| 00:00:06 |
| 3 | NESTED LOOPS OUTER | | 1 | 188 | 441 (2)| 00:00:06 |
| 4 | NESTED LOOPS OUTER | | 1 | 185 | 441 (2)| 00:00:06 |
| 5 | NESTED LOOPS OUTER | | 1 | 168 | 439 (2)| 00:00:06 |
| 6 | NESTED LOOPS OUTER | | 1 | 159 | 438 (2)| 00:00:06 |
|* 7 | FILTER | | | | | |
| 8 | NESTED LOOPS OUTER | | 1 | 153 | 437 (2)| 00:00:06 |
| 9 | NESTED LOOPS OUTER | | 47 | 6392 | 343 (3)| 00:00:05 |
| 10 | NESTED LOOPS | | 46 | 6026 | 297 (3)| 00:00:04 |
|* 11 | HASH JOIN OUTER | | 46 | 5888 | 297 (3)| 00:00:04 |
|* 12 | HASH JOIN | | 41 | 4961 | 294 (3)| 00:00:04 |
|* 13 | HASH JOIN | | 41 | 4674 | 292 (3)| 00:00:04 |
|* 14 | HASH JOIN OUTER | | 3 | 24 | 3 (34)| 00:00:01 |
| 15 | INDEX FULL SCAN | COM_DOCUMENT_TYPES_PK | 3 | 9 | 1 (0)| 00:00:01 |
|* 16 | INDEX FULL SCAN | COM_DOCUMENT_TYPES_MLD_PK | 3 | 15 | 1 (0)| 00:00:01 |
|* 17 | TABLE ACCESS BY INDEX ROWID| COM_DOCUMENTS | 41 | 4346 | 289 (3)| 00:00:04 |
|* 18 | INDEX RANGE SCAN | COM_DOCUMENTS_IDX2 | 8064 | | 17 (6)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | WF_PROCESS_STATUS | 5 | 35 | 2 (0)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | WF_PROCESS_STATUS_IDX1 | 5 | | 1 (0)| 00:00:01 |
|* 21 | TABLE ACCESS FULL | WF_PROCESS_STATUS_MLD | 24 | 168 | 2 (0)| 00:00:01 |
|* 22 | INDEX UNIQUE SCAN | SYS_C0021772 | 1 | 3 | 0 (0)| 00:00:01 |
|* 23 | INDEX RANGE SCAN | COM_MUNICIPAL_LICENSE_IDX2 | 1 | 5 | 1 (0)| 00:00:01 |
| 24 | TABLE ACCESS BY INDEX ROWID | LCT_SPONSOR | 1 | 17 | 2 (0)| 00:00:01 |
|* 25 | INDEX UNIQUE SCAN | LCT_SPONSOR_PK | 1 | | 1 (0)| 00:00:01 |
|* 26 | INDEX UNIQUE SCAN | AUTH_USERS_PK | 1 | 6 | 1 (0)| 00:00:01 |
|* 27 | INDEX UNIQUE SCAN | AUTH_USERS_MLD_UK1 | 1 | 9 | 1 (0)| 00:00:01 |
| 28 | TABLE ACCESS BY INDEX ROWID | LCT_SPONSOR_BRANCHES | 1 | 17 | 2 (0)| 00:00:01 |
|* 29 | INDEX UNIQUE SCAN | BRANCHES_ID1 | 1 | | 1 (0)| 00:00:01 |
|* 30 | INDEX UNIQUE SCAN | LCM_REGION_PK | 1 | 3 | 0 (0)| 00:00:01 |
|* 31 | INDEX UNIQUE SCAN | LCM_WILAYAT_PK | 1 | 4 | 0 (0)| 00:00:01 |
|* 32 | INDEX UNIQUE SCAN | LCM_VILLAGE_PK | 1 | 10 | 0 (0)| 00:00:01 |
下面给出了完整的查询查询,供您参考:
SET SERVEROUTPUT ON;
DECLARE
CR VARCHAR2(32767) := '1048830';
DUID VARCHAR2(32767) := '1048830-10804-7174-72';
ST NUMBER := 105;
DTID NUMBER := 2;
RESP VARCHAR2(32767);
BEGIN
SELECT D.*
FROM COM_DOCUMENTS D
INNER JOIN SYS_LABOUR_OFFICE LO ON D.LABOUR_OFFICE_ID=LO.ID
LEFT JOIN COM_MUNICIPAL_LICENSE ML ON D.ID = ML.DOCUMENT_ID
LEFT JOIN LCT_SPONSOR SP ON D.SPONSOR_NO = SP.SPONSOR_NO
LEFT JOIN LCT_SPONSOR_BRANCHES LSB ON D.BRANCH_NO =LSB.ID
INNER JOIN WF_PROCESS_STATUS PS ON D.CURRENT_STATUS_ID = PS.WF_PROCESS_STATUS_ID AND PS.WF_PROCESS_ID = 6
LEFT JOIN WF_PROCESS_STATUS_MLD PSMLD ON PS.WF_PROCESS_STATUS_ID = PSMLD.WF_PROCESS_STATUS_ID AND PSMLD.LANGUAGE_ID = 1
LEFT JOIN AUTH_USERS AU1 ON D.CURRENT_FOLLOWER = AU1.USER_ID
LEFT JOIN AUTH_USERS_MLD AU_MLD1 ON AU1.USER_ID = AU_MLD1.USER_ID AND AU_MLD1.LANGUAGE_ID = 1
INNER JOIN COM_DOCUMENT_TYPES DT ON D.DOC_TYPE_ID = DT.DOCUMENT_TYPE_ID
LEFT JOIN COM_DOCUMENT_TYPES_MLD DTM ON DT.DOCUMENT_TYPE_ID = DTM.DOCUMENT_TYPE_ID AND DTM.LANGUAGE_ID=1
LEFT JOIN LCM_REGION LR ON LSB.REGION_CODE = LR.REGION_CODE
LEFT JOIN LCM_WILAYAT LW ON LSB.REGION_CODE = LW.REGION_CODE AND LSB.WILAYAT_CODE = LW.WILAYAT_CODE
LEFT JOIN LCM_VILLAGE LV ON LSB.REGION_CODE = LV.REGION_CODE AND LSB.WILAYAT_CODE = LV.WILAYAT_CODE AND LSB.VILLAGE_CODE = LV.VILLAGE_CODE
WHERE (CR = '' OR SP.CR_NO = CR)
AND (DUID = '' OR D.DOC_UNIQUE_IDENTIFIER = NVL(DUID, D.DOC_UNIQUE_IDENTIFIER))
AND (ST = -99 OR D.CURRENT_STATUS_ID = ST)
AND (DTID = -99 OR D.DOC_TYPE_ID = DTID);
DBMS_OUTPUT.PUT_LINE(RESP);
END;
我对oracle非常陌生,我需要了解如何阅读此解释计划。
我实际上需要了解如何通过阅读解释计划来优化查询和加入订单等。希望这对很多人有帮助。
答案 0 :(得分:0)
我会这样开始。 表是否已分区并且对哪些列进行了索引? 这些表是否有最新统计信息?甲骨文拥有做出明智选择所需的一切吗? 我是否要删除/截断分区并使用append将其插入/插入这些表中,因为如果我使用带有insert的插入进行删除,HWM会成为一个问题。
您想要的是拥有Oracle,做出正确的执行计划选择。您需要表,分区和索引具有最新的统计信息。
begin
DBMS_STATS.GATHER_TABLE_STATS
(OWNNAME => lv_schema_from,
TABNAME => lv_table_from,
ESTIMATE_PERCENT => 15, --15% for ~100000 of record, 15%-100% for less METHOD_OPT => 'FOR ALL COLUMNS SIZE AUTO',
GRANULARITY => 'AUTO', --only if you have partitioned table
DEGREE => 8, --parallel
CASCADE => TRUE); --cascade to indexes
end;
这可能会改变执行计划(更好)。
然后,如果是相同的执行计划,我将从表和并行提示之间的联接类型开始(有多少个内核可用?)。
哪个更好?首先从D或LO读取->在表的最小表上进行前导提示,它们之间具有内部联接(以防万一)。
我要使用索引吗?如果我使用索引将9.000.000条记录查找到300.000.000表(3%)中,则可能需要半小时。就我而言,use_hash或完整提示比让oracle进行索引要快。
实验...不同数量的内核,PGA,SGA,统计数据(最重要)使CBO对同一查询的最佳执行计划进行不同的评估。
最好的方法是找到问题的根源,这将是为什么Oracle为什么选择此执行计划的答案? 大多数时候,表,分区和索引的统计信息。