Предоставление ключа секционирования для секционированной таблицы увеличивает стоимость запроса - PullRequest
0 голосов
/ 18 января 2019

Я работаю над веб-приложением, которое запрашивает таблицы, содержащие большие объемы данных. Из-за проблем с производительностью пользовательского интерфейса - я изучал способы повышения производительности долго выполняющихся запросов.

Пожалуйста, смотрите ниже пример нашего оригинального кода и плана объяснения.

 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?

Спасибо за помощь! Билли

EDIT:

В этом примере ...

T1 имеет 625 417 строк

T2 имеет 577 718 строк

Все строки из T1 соответствуют условию соединения в T2

57 355 строк в T1 соответствуют T1.EMPLOYEE_ID = '1001' И T1.RUN_TIMESTAMP = '16 -JAN-19 17.39.36.000000000

T2 имеет уникальный индекс по идентификатору и не разделен

1 Ответ

0 голосов
/ 18 января 2019

У меня была ситуация, когда я соединял две таблицы, обе таблицы были разделены. Запрос использовал индекс для первой таблицы, но выполнил полное сканирование таблицы во второй таблице. Я добавил подсказку для использования индекса на второй таблице. С этой подсказкой план объяснения показал запрос с использованием индекса во второй таблице.
Если у вас есть индекс для T2.ID, я предлагаю вам добавить подсказку к вашему запросу для этого индекса.

...