我有两个表 MP_LM 和 MP_BS,这两个表如下所示连接到一个 View 并在 select 语句中使用。
CREATE VIEW MV_MP_LM_V (MP_ID,ID,PID,NAME,IS_D) AS
SELECT C.mp_ID,C.BS_ID ID,NULL PID,C.BS_NM NAME,'Y' IS_D FROM MP_BS C UNION
SELECT CM.mp_ID,CM.LM_ID ID,CM.IT_ID PID,CM.LM_NM NAME,CM.IS_D FROM MP_LC_REF_ORIG CM WHERE FLG = 'Y' ;
表 MP_BS 的 PK 如下。
ALTER TABLE MP_BS ADD CONSTRAINT MP_BS_PK PRIMARY KEY (MP_ID, BS_ID, BS_NM);
下面是我正在运行的 Select。
SELECT DISTINCT
ID,
PID,
NAME,
DECODE (pid,
NULL, DECODE (id, -1, NULL, id || '$'),
pid || '$' || id)
tree_id,
DECODE (ID, -1, 0, 1) s1
FROM MV_MP_LM_V, TABLE (MV_SPLITARR5 (336700164 , ',', '$')) c
WHERE mp_ID = c.id1
AND IS_D= 'Y'
AND ID <> -1
AND ( 0 = 0
OR ( 0 > 0
))
ORDER BY s1, DECODE (pid, NULL, 0, 1), name;
对于上面的选择,没有索引 MP_BS_PK ,选择需要 35 秒,下面是计划..
Plan hash value: 2313865915
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 206M| 123G| | 56M (1)|188:17:27 |
| 1 | SORT ORDER BY | | 206M| 123G| 131G| 56M (1)|188:17:27 |
| 2 | HASH UNIQUE | | 206M| 123G| 131G| 28M (1)| 94:49:48 |
|* 3 | HASH JOIN | | 206M| 123G| | 410K (1)| 01:22:09 |
| 4 | COLLECTION ITERATOR PICKLER FETCH| MV_SPLITARR5 | 8168 | 16336 | | 29 (0)| 00:00:01 |
| 5 | VIEW | MV_MP_LM_V | 2529K| 1546M| | 409K (1)| 01:21:56 |
| 6 | SORT UNIQUE | | 2529K| 1489M| 1572M| 409K (1)| 01:21:56 |
| 7 | UNION-ALL | | | | | | |
|* 8 | TABLE ACCESS FULL | MP_BS | 121K| 2964K| | 377 (1)| 00:00:05 |
|* 9 | TABLE ACCESS FULL | MP_LM_REF_ORIG | 2408K| 1486M| | 79820 (1)| 00:15:58 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("MP_ID"=TO_NUMBER(SYS_OP_ATG(VALUE(KOKBF$),1,2,2)))
8 - filter("C"."BS_ID"<>(-1))
9 - filter("CM"."LM_ID"<>(-1) AND "FLG"='Y' AND "CM"."IS_D"='Y')
Note
-----
- dynamic sampling used for this statement (level=2)
使用 pk,选择需要 10 秒,下面是计划。
Plan hash value: 2486203413
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 1929 | 26028 (1)| 00:05:13 |
| 1 | SORT ORDER BY | | | 1929 | 26028 (1)| 00:05:13 |
| 2 | HASH UNIQUE | | | 1929 | 26027 (1)| 00:05:13 |
|* 3 | HASH JOIN | | 3 | 1929 | 26026 (1)| 00:05:13 |
| 4 | VIEW | MV_MP_LM_V | 10 | 6410 | 25997 (1)| 00:05:12 |
| 5 | SORT UNIQUE | | | | | |
| 6 | UNION-ALL | | | | | |
|* 7 | INDEX FAST FULL SCAN | MP_BS_PK | 121K| 2964K| 192 (1)| 00:00:03 |
|* 8 | TABLE ACCESS FULL | MP_LM_REF_ORIG | 2408K| 1486M| 79820 (1)| 00:15:58 |
| 9 | COLLECTION ITERATOR PICKLER FETCH| MV_SPLITARR5 | 8168 | 16336 | 29 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("MP_ID"=TO_NUMBER(SYS_OP_ATG(VALUE(KOKBF$),1,2,2)))
7 - filter("C"."BS_ID"<>(-1))
8 - filter("CM"."LM_ID"<>(-1) AND "FLG"='Y' AND "CM"."IS_D"='Y')
Note
-----
- dynamic sampling used for this statement (level=2)
我研究了很多东西,但无法找出为什么较小表上的 pk/index 性能更快。
没有。每个表中的行数是:
MP_LM_REF_ORIG :- 10241670
MP_BS :- 147575
我尝试在 ID 为 MP_ID 的表 MP_LM_REF_ORIG 上创建索引,但未使用该索引。
谁能解释一下 MP_BS 上的这个索引如何帮助提高性能。
最佳答案
至少有两个原因:
INDEX FAST FULL SCAN
而不是TABLE ACCESS FULL
即,它不是对表进行全面扫描,而是对索引进行全面扫描,这可能更小然后对应表UNION
要求删除重复的行,这在计划中由union all
后跟sort unique
表示。当使用索引时,使用索引返回的数据已经排序,因此可以在性能上获得另一个好处。
关于Oracle - 未使用大表上的索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29220798/