我正在研究一个Web应用程序,该应用程序查询包含大量数据的表。由于UI性能问题-我一直在研究改善长期运行查询性能的方法。
请在下面查看我们原始代码和说明计划的示例。
EXPLAIN PLAN FOR
SELECT * FROM T1
INNER JOIN T2 ON (T2.ID = T1.ID)
WHERE
T1.EMPLOYEE_ID = '1001'
AND T1.RUN_TIMESTAMP = '16-JAN-19 17.39.36.000000000'
-----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 37183 | 31M| | 37654 (1)| 00:00:02 |
|* 1 | HASH JOIN | | 37183 | 31M| 6688K| 37654 (1)| 00:00:02 |
|* 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T1 | 37183 | 6245K| | 2492 (1)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_T1_RT | 76305 | | | 410 (1)| 00:00:01 |
| 4 | TABLE ACCESS FULL | T2 | 577K| 399M| | 14704 (1)| 00:00:01 |
-----------------------------------------------------------------------------------------------------------------------------
已创建表格
为了提高查询性能-我决定按值对大表T1进行分区。创建了45个分区,其中覆盖了表中每个条目所分配的45个不同的值。在此示例中-值1-45。
将数据从T1迁移到分区表T1_PART并提供了不同的分区键之后,我很失望地看到尽管现在仅按预期扫描单个分区。成本收益只是微不足道的。
EXPLAIN PLAN FOR
SELECT * FROM T1_PART
INNER JOIN T2 ON (T2.ID = T1.ID)
WHERE
T1.EMPLOYEE_ID = '1001'
AND T1.PARTITION_KEY = '1'
AND T1.RUN_TIMESTAMP = '16-JAN-19 17.39.36.000000000'
----------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 19912 | 17M| | 37341 (1)| 00:00:02 | | |
|* 1 | HASH JOIN | | 19912 | 17M| 3680K| 37341 (1)| 00:00:02 | | |
| 2 | PARTITION LIST SINGLE | | 19912 | 3441K| | 2131 (1)| 00:00:01 | KEY | KEY |
|* 3 | TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T1_PART | 19912 | 3441K| | 2131 (1)| 00:00:01 | 19 | 19 |
|* 4 | INDEX RANGE SCAN | IDX_T1_RT | 57355 | | | 276 (1)| 00:00:01 | 19 | 19 |
| 5 | TABLE ACCESS FULL | T2 | 577K| 403M| | 14706 (1)| 00:00:01 | | |
----------------------------------------------------------------------------------------------------------------------------------------------------
但是,真正让我感兴趣的是-当我不再指定分区键时-查询的成本大大降低了。
我们可以从计划中看出,我们现在对表进行完整扫描,但是现在使用我没有想到的某种形式的并行化来执行。
EXPLAIN PLAN FOR
SELECT * FROM T1_PART
INNER JOIN T2 ON (T2.ID = T1.ID)
WHERE
T1.EMPLOYEE_ID = '1001'
AND T1.RUN_TIMESTAMP = '16-JAN-19 17.39.36.000000000'
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 19912 | 17M| 16926 (1)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | 19912 | 17M| 16926 (1)| 00:00:01 | | | Q1,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN BUFFERED | | 19912 | 17M| 16926 (1)| 00:00:01 | | | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | 19912 | 3519K| 2217 (1)| 00:00:01 | | | Q1,02 | PCWP | |
| 5 | PX SEND HYBRID HASH | :TQ10000 | 19912 | 3519K| 2217 (1)| 00:00:01 | | | Q1,00 | P->P | HYBRID HASH|
| 6 | STATISTICS COLLECTOR | | | | | | | | Q1,00 | PCWC | |
| 7 | PX PARTITION LIST ALL | | 19912 | 3519K| 2217 (1)| 00:00:01 | 1 | 45 | Q1,00 | PCWC | |
|* 8 | TABLE ACCESS BY LOCAL INDEX ROWID BATCHED| T1_PART | 19912 | 3519K| 2217 (1)| 00:00:01 | 1 | 45 | Q1,00 | PCWP | |
|* 9 | INDEX RANGE SCAN | IDX_T1_RT | 57355 | | 383 (1)| 00:00:01 | 1 | 45 | Q1,00 | PCWP | |
| 10 | PX RECEIVE | | 577K| 403M| 14706 (1)| 00:00:01 | | | Q1,02 | PCWP | |
| 11 | PX SEND HYBRID HASH | :TQ10001 | 577K| 403M| 14706 (1)| 00:00:01 | | | Q1,01 | S->P | HYBRID HASH|
| 12 | PX SELECTOR | | | | | | | | Q1,01 | SCWC | |
| 13 | TABLE ACCESS FULL | T2 | 577K| 403M| 14706 (1)| 00:00:01 | | | Q1,01 | SCWP | |
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
有人知道这里可能发生什么吗?有没有办法在SQL的并行执行中仅利用单个分区扫描?
感谢您的帮助! 比利
编辑:
在此示例中...
T1有625,417行
T2有577,718行
T1中的所有行都符合T2上的连接条件
T1中的57,355行与T1.EMPLOYEE_ID ='1001'和T1.RUN_TIMESTAMP = '19 -JAN-19 17.39.36.000000000匹配
T2在ID上具有唯一索引,并且未分区
答案 0 :(得分:0)
我遇到的情况是我加入了两个表,两个表都已分区。该查询在第一个表上使用了索引,但对第二个表执行了全表扫描。我在第二个表上添加了使用索引的提示。有了这个提示,解释计划便使用第二个表上的索引显示了查询。
如果您在T2.ID上有索引,建议您在查询中为该索引添加提示。