为分区表提供分区键会增加查询成本

时间:2019-01-18 17:13:09

标签: sql database oracle performance partition

我正在研究一个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上具有唯一索引,并且未分区

1 个答案:

答案 0 :(得分:0)

我遇到的情况是我加入了两个表,两个表都已分区。该查询在第一个表上使用了索引,但对第二个表执行了全表扫描。我在第二个表上添加了使用索引的提示。有了这个提示,解释计划便使用第二个表上的索引显示了查询。
如果您在T2.ID上有索引,建议您在查询中为该索引添加提示。