У меня есть таблица «обсуждение», структура которой выглядит следующим образом:
Название таблицы: обсуждение,
Id name parent_id root_id ...other columns
1 discussion1 0 0
2 discussion2 1 1
3 discussion3 2 1
4 discussion4 3 1
5 discussion5 4 1
Очевидно, что id был определен как PK, parent_id и root_id были проиндексированы.
эти строки таблицы были построены как иерархические отношения (вроде parent-> child), а также обратите внимание, что столбец root_id используется для описания этих строк в одном и том же дереве.
Я написал два SQL для получения дерева потоков:
SQL 1
SELECT *
from discussion
start with (parent_Id=0 AND id=?)
connect by prior Id=parent_Id
SQL 2
SELECT * FROM (
SELECT * FROM discussion WHERE root_id = ? or id = ?
)START WITH (parent_Id=0 AND id=?) connect by prior Id=parent_Id
После моего теста, если наборы данных около 4000, SQL 1 работал немного лучше, чем SQL2.
Но если обсуждение таблицы имеет очень большие данные, SQL 2 работал намного лучше, чем SQL1.
Когда в таблице 300 тысяч строк, план запроса сообщает, что стоимость SQL 1 равна 22126, стоимость SQL 2 - 6. SQL 1 включается в полную проверку таблицы или SQL 2 получает сканирование индекса диапазона.
Кто-нибудь может мне помочь объяснить, почему два SQL показывают разные результаты с разными номерами данных?
Более важно, я хочу, чтобы ваши ребята предложили улучшить производительность или другое решение?
Вот план запроса для SQL 1 , когда у нас 300 тысяч строк.
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name : staName52149
Tuning Task Owner : CISCO
Tuning Task ID : 54
Workload Type : Single SQL Statement
Execution Count : 1
Current Execution : EXEC_44
Execution Type : TUNE SQL
Scope : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status : COMPLETED
Started at : 10/23/2011 23:23:31
Completed at : 10/23/2011 23:23:59
-------------------------------------------------------------------------------
Schema Name: CISCO
SQL ID : davhv6p4x6bu2
SQL Text : SELECT * from discussion start with (parent_Id=0 AND id=6587)
connect by prior Id=parent_Id
-------------------------------------------------------------------------------
FINDINGS SECTION (1 finding)
-------------------------------------------------------------------------------
1- SQL Profile Finding (see explain plans section below)
--------------------------------------------------------
A potentially better execution plan was found for this statement.
Recommendation (estimated benefit: 99.99%)
------------------------------------------
- Consider accepting the recommended SQL profile.
execute dbms_sqltune.accept_sql_profile(task_name => 'staName52149',
task_owner => 'CISCO', replace => TRUE);
Validation results
------------------
The SQL profile was tested by executing both its plan and the original plan
and measuring their respective execution statistics. A plan may have been
only partially executed if the other could be run to completion in less time.
Original Plan With SQL Profile % Improved
------------- ---------------- ----------
Completion Status: COMPLETE COMPLETE
Elapsed Time(us): 14251990 121 99.99 %
CPU Time(us): 3463222 0 100 %
User I/O Time(us): 10821745 0 100 %
Buffer Gets: 678361 6 99.99 %
Physical Read Requests: 1013 0 100 %
Physical Write Requests: 1081 0 100 %
Physical Read Bytes: 234168320 0 100 %
Physical Write Bytes: 223756288 0 100 %
Rows Processed: 1 1
Fetches: 1 1
Executions: 1 1
Notes
-----
1. The SQL profile plan was first executed to warm the buffer cache.
2. Statistics for the SQL profile plan were averaged over next 9 executions.
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------
1- Original
-----------
Plan hash value: 2811036397
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 348K| 2770M| 22162 (82)| 00:04:26 |
|* 1 | CONNECT BY NO FILTERING WITH START-WITH| | | | | |
| 2 | TABLE ACCESS FULL | DISCUSSION | 348K| 79M| 4108 (1)| 00:00:50 |
------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$2 / DISCUSSION@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DISCUSSION"."PARENT_ID"=PRIOR NULL)
filter("PARENT_ID"=0 AND "ID"=6587)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "DISCUSSION"."PARENT_ID"[NUMBER,22], "DISCUSSION"."ID"[NUMBER,22], STRDEF[22],
STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[4000], STRDEF[22], STRDEF[22],
STRDEF[150], STRDEF[7], STRDEF[7], STRDEF[4000], STRDEF[22], STRDEF[22], STRDEF[22],
STRDEF[4000], STRDEF[22], STRDEF[4000], STRDEF[7], STRDEF[22], STRDEF[32], STRDEF[22],
STRDEF[22], STRDEF[22], STRDEF[7], STRDEF[7], PRIOR NULL[22], LEVEL[4]
2 - "ID"[NUMBER,22], "DISCUSSION"."CLASS"[NUMBER,22], "DISCUSSION"."SUBCLASS"[NUMBER,22],
"PARENT_ID"[NUMBER,22], "DISCUSSION"."ROOT_ID"[NUMBER,22],
"DISCUSSION"."MESSAGE"[VARCHAR2,4000], "DISCUSSION"."STATUS"[NUMBER,22],
"DISCUSSION"."PRIORITY"[NUMBER,22], "DISCUSSION"."AUTO_NUMBER"[VARCHAR2,150],
"DISCUSSION"."CREATE_DATE"[DATE,7], "DISCUSSION"."CLOSE_DATE"[DATE,7],
"DISCUSSION"."CLOSE_COMMENTS"[VARCHAR2,4000], "DISCUSSION"."ORGANIZATION"[NUMBER,22],
"DISCUSSION"."TYPE"[NUMBER,22], "DISCUSSION"."CREATOR"[NUMBER,22],
"DISCUSSION"."SUBJECT"[VARCHAR2,4000], "DISCUSSION"."REPLIES"[NUMBER,22],
"DISCUSSION"."NOTIFYLIST"[VARCHAR2,4000], "DISCUSSION"."LAST_REPLY_DATE"[DATE,7],
"DISCUSSION"."DELETE_FLAG"[NUMBER,22], "DISCUSSION"."FLAGS"[VARCHAR2,32],
"DISCUSSION"."PREVIEW_TEXT"[NUMBER,22], "DISCUSSION"."FILTER"[NUMBER,22],
"DISCUSSION"."OBJVERSION"[NUMBER,22], "DISCUSSION"."CREATED"[DATE,7],
"DISCUSSION"."LAST_UPD"[DATE,7]
2- Original With Adjusted Cost
------------------------------
Plan hash value: 2811036397
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 348K| 2770M| 22162 (82)| 00:04:26 |
|* 1 | CONNECT BY NO FILTERING WITH START-WITH| | | | | |
| 2 | TABLE ACCESS FULL | DISCUSSION | 348K| 79M| 4108 (1)| 00:00:50 |
------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$2 / DISCUSSION@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DISCUSSION"."PARENT_ID"=PRIOR NULL)
filter("PARENT_ID"=0 AND "ID"=6587)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "DISCUSSION"."PARENT_ID"[NUMBER,22], "DISCUSSION"."ID"[NUMBER,22], STRDEF[22],
STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[4000], STRDEF[22], STRDEF[22],
STRDEF[150], STRDEF[7], STRDEF[7], STRDEF[4000], STRDEF[22], STRDEF[22], STRDEF[22],
STRDEF[4000], STRDEF[22], STRDEF[4000], STRDEF[7], STRDEF[22], STRDEF[32], STRDEF[22],
STRDEF[22], STRDEF[22], STRDEF[7], STRDEF[7], PRIOR NULL[22], LEVEL[4]
2 - "ID"[NUMBER,22], "DISCUSSION"."CLASS"[NUMBER,22], "DISCUSSION"."SUBCLASS"[NUMBER,22],
"PARENT_ID"[NUMBER,22], "DISCUSSION"."ROOT_ID"[NUMBER,22],
"DISCUSSION"."MESSAGE"[VARCHAR2,4000], "DISCUSSION"."STATUS"[NUMBER,22],
"DISCUSSION"."PRIORITY"[NUMBER,22], "DISCUSSION"."AUTO_NUMBER"[VARCHAR2,150],
"DISCUSSION"."CREATE_DATE"[DATE,7], "DISCUSSION"."CLOSE_DATE"[DATE,7],
"DISCUSSION"."CLOSE_COMMENTS"[VARCHAR2,4000], "DISCUSSION"."ORGANIZATION"[NUMBER,22],
"DISCUSSION"."TYPE"[NUMBER,22], "DISCUSSION"."CREATOR"[NUMBER,22],
"DISCUSSION"."SUBJECT"[VARCHAR2,4000], "DISCUSSION"."REPLIES"[NUMBER,22],
"DISCUSSION"."NOTIFYLIST"[VARCHAR2,4000], "DISCUSSION"."LAST_REPLY_DATE"[DATE,7],
"DISCUSSION"."DELETE_FLAG"[NUMBER,22], "DISCUSSION"."FLAGS"[VARCHAR2,32],
"DISCUSSION"."PREVIEW_TEXT"[NUMBER,22], "DISCUSSION"."FILTER"[NUMBER,22],
"DISCUSSION"."OBJVERSION"[NUMBER,22], "DISCUSSION"."CREATED"[DATE,7],
"DISCUSSION"."LAST_UPD"[DATE,7]
3- Using SQL Profile
--------------------
Plan hash value: 3458076016
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 16686 | 11 (28)| 00:00:01 |
|* 1 | CONNECT BY WITH FILTERING | | | | | |
|* 2 | TABLE ACCESS BY INDEX ROWID | DISCUSSION | 1 | 240 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | DISCUSSION_PK | 1 | | 2 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 1 | 253 | 5 (0)| 00:00:01 |
| 5 | CONNECT BY PUMP | | | | | |
| 6 | TABLE ACCESS BY INDEX ROWID| DISCUSSION | 1 | 240 | 3 (0)| 00:00:01 |
|* 7 | INDEX RANGE SCAN | DISC_IDX_PARENTID | 1 | | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$4 / DISCUSSION@SEL$4
3 - SEL$4 / DISCUSSION@SEL$4
4 - SEL$3
6 - SEL$3 / DISCUSSION@SEL$3
7 - SEL$3 / DISCUSSION@SEL$3
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DISCUSSION"."PARENT_ID"=PRIOR NULL)
2 - filter("PARENT_ID"=0)
3 - access("ID"=6587)
7 - access("connect$_by$_pump$_002"."prior Id"="PARENT_ID")
Вот план запроса для SQL 2 , когда у нас 300 тысяч строк.
GENERAL INFORMATION SECTION
-------------------------------------------------------------------------------
Tuning Task Name : staName64031
Tuning Task Owner : CISCO
Tuning Task ID : 55
Workload Type : Single SQL Statement
Execution Count : 1
Current Execution : EXEC_45
Execution Type : TUNE SQL
Scope : COMPREHENSIVE
Time Limit(seconds): 1800
Completion Status : COMPLETED
Started at : 10/23/2011 23:30:22
Completed at : 10/23/2011 23:30:26
-------------------------------------------------------------------------------
Schema Name: CISCO
SQL ID : c741jfryv5m98
SQL Text : SELECT * FROM (
SELECT * FROM discussion WHERE root_id = 6587 or
id = 6587
)Start With (Parent_Id=0 And Id=6587) Connect By
Prior Id=Parent_Id
-------------------------------------------------------------------------------
There are no recommendations to improve the statement.
-------------------------------------------------------------------------------
EXPLAIN PLANS SECTION
-------------------------------------------------------------------------------
1- Original
-----------
Plan hash value: 1202872009
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 16686 | 6 (17)| 00:00:01 |
|* 1 | CONNECT BY NO FILTERING WITH START-WITH| | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | DISCUSSION | 2 | 480 | 5 (0)| 00:00:01 |
| 3 | BITMAP CONVERSION TO ROWIDS | | | | | |
| 4 | BITMAP OR | | | | | |
| 5 | BITMAP CONVERSION FROM ROWIDS | | | | | |
|* 6 | INDEX RANGE SCAN | DISCUSSION_PK | | | 2 (0)| 00:00:01 |
| 7 | BITMAP CONVERSION FROM ROWIDS | | | | | |
|* 8 | INDEX RANGE SCAN | DISC_IDX_ROOTID | | | 3 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$1
2 - SEL$E029B2FF / DISCUSSION@SEL$5
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DISCUSSION"."PARENT_ID"=PRIOR NULL)
filter("DISCUSSION"."PARENT_ID"=0 AND "DISCUSSION"."ID"=6587)
6 - access("ID"=6587)
8 - access("ROOT_ID"=6587)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "DISCUSSION"."PARENT_ID"[NUMBER,22], "DISCUSSION"."ID"[NUMBER,22], STRDEF[22], STRDEF[22],
STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[4000], STRDEF[22], STRDEF[22], STRDEF[150], STRDEF[7],
STRDEF[7], STRDEF[4000], STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[4000], STRDEF[22],
STRDEF[4000], STRDEF[7], STRDEF[22], STRDEF[32], STRDEF[22], STRDEF[22], STRDEF[22], STRDEF[7],
STRDEF[7], PRIOR NULL[22], LEVEL[4]
2 - "DISCUSSION".ROWID[ROWID,10], "ID"[NUMBER,22], "DISCUSSION"."CLASS"[NUMBER,22],
"DISCUSSION"."SUBCLASS"[NUMBER,22], "DISCUSSION"."PARENT_ID"[NUMBER,22], "ROOT_ID"[NUMBER,22],
"DISCUSSION"."MESSAGE"[VARCHAR2,4000], "DISCUSSION"."STATUS"[NUMBER,22],
"DISCUSSION"."PRIORITY"[NUMBER,22], "DISCUSSION"."AUTO_NUMBER"[VARCHAR2,150],
"DISCUSSION"."CREATE_DATE"[DATE,7], "DISCUSSION"."CLOSE_DATE"[DATE,7],
"DISCUSSION"."CLOSE_COMMENTS"[VARCHAR2,4000], "DISCUSSION"."ORGANIZATION"[NUMBER,22],
"DISCUSSION"."TYPE"[NUMBER,22], "DISCUSSION"."CREATOR"[NUMBER,22],
"DISCUSSION"."SUBJECT"[VARCHAR2,4000], "DISCUSSION"."REPLIES"[NUMBER,22],
"DISCUSSION"."NOTIFYLIST"[VARCHAR2,4000], "DISCUSSION"."LAST_REPLY_DATE"[DATE,7],
"DISCUSSION"."DELETE_FLAG"[NUMBER,22], "DISCUSSION"."FLAGS"[VARCHAR2,32],
"DISCUSSION"."PREVIEW_TEXT"[NUMBER,22], "DISCUSSION"."FILTER"[NUMBER,22],
"DISCUSSION"."OBJVERSION"[NUMBER,22], "DISCUSSION"."CREATED"[DATE,7],
"DISCUSSION"."LAST_UPD"[DATE,7]
3 - "DISCUSSION".ROWID[ROWID,10]
4 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 16116]
5 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 16116]
6 - "DISCUSSION".ROWID[ROWID,10]
7 - STRDEF[BM VAR, 10], STRDEF[BM VAR, 10], STRDEF[BM VAR, 16116]
8 - "DISCUSSION".ROWID[ROWID,10]
-------------------------------------------------------------------------------