Выполнение запроса с более низкой стоимостью - PullRequest
0 голосов
/ 09 января 2020

Я пытаюсь оптимизировать оператор выбора, но, похоже, чем больше он уменьшается в стоимости, тем дольше он выполняется. Что здесь происходит?

Я могу добавить фильтр для partition_type, который значительно снижает стоимость запроса, я думаю, потому что необходимость полного сканирования таблицы исчезает из плана объяснения. Существует также вложенный запрос, который возвращает одну строку, содержащую ключ partition_, активный сегодня. Оставление вложенного запроса увеличивает стоимость до 20 МБ (полное сканирование таблицы, хотя и небольшой таблицы). Замена вложенного запроса фактическим результатом этого запроса снова снижает стоимость. Поэтому, если я выполню запрос следующим образом:

  • Вложенный запрос, без partition_type: стоимость 20.233.522
  • Фиксированное значение, без partition_type: стоимость 234.712
  • Фиксированное значение , partition_type: cost 9.611

Мои вопросы:

  • Как запрос с наименьшими затратами (безусловно) не быстрее, чем остальные, с большим отрывом, но медленнее?
  • Как вложенный запрос фактического ключа раздела может значительно увеличить стоимость? Я знаю, что это полное сканирование таблицы, но это как 8 байтов.

Объясните планы и запрос ниже.

Запрос:

SELECT CASE WHEN COUNT (*) > 0 THEN 0 ELSE 1 END AS result
FROM MYTABLE.ORDERS  O
   INNER JOIN MYTABLE.BATCH B
       ON     B.BATCH_ID = O.IN_BATCH_ID
          AND B.PARTITION_KEY = O.PARTITION_KEY
          AND B.PARTITION_TYPE = O.PARTITION_TYPE
          AND B.INSTANCE_NUMBER = O.INSTANCE_NUMBER
WHERE     O.PARTITION_KEY = (SELECT actual_partition_key
                            FROM MYTABLE.CALENDAR
                           WHERE is_active = 1) --can replace this with fixed value 123
   AND O.partition_type = 3 -- can leave this one out
   AND B.START_TIME > SYSDATE - 1 / 2 / 24
   AND B.START_TIME < SYSDATE - 10 / 60 / 24
   AND O.STATE NOT IN ('993890', '999990')
   AND O.RECEIVER IN
           (SELECT RECEIVER_ID
              FROM (  SELECT MAX (CREATION_DATE) AS CREATION_DATE,
                             RECEIVER_ID
                        FROM MYTABLE.RECEIVER_AVAILABILITY
                    GROUP BY RECEIVER_ID) MAX_CREATION_DATE
                   INNER JOIN MYTABLE.RECEIVER_AVAILABILITY
                       ON MAX_CREATION_DATE.CREATION_DATE = CREATION_DATE
             WHERE     state IN (1, 2)
                   AND creation_date < SYSDATE - 30 / 60 / 24)

Самый тяжелый запрос, без тип_раздела и вложенный запрос для выбора текущего раздела: Время выполнения: 2 se c

    Plan
    SELECT STATEMENT  ALL_ROWSCost: 20.233.522  Bytes: 60  Cardinality: 1                                                           
           21 SORT AGGREGATE  Bytes: 60  Cardinality: 1                                                  
                 20 FILTER                                             
                        10 FILTER                                      
                               9 NESTED LOOPS  Cost: 20.233.494  Bytes: 60  Cardinality: 1                                   
                                      7 NESTED LOOPS  Cost: 20.233.494  Bytes: 60  Cardinality: 113                          
                                            4 PARTITION RANGE ITERATOR  Cost: 20.233.267  Bytes: 3.842  Cardinality: 113  Partition #: 6  Partitions determined by Key Values                  
                                                   3 PARTITION HASH ALL  Cost: 20.233.267  Bytes: 3.842  Cardinality: 113  Partition #: 7  Partitions accessed #1 - #2             
                                                          2 TABLE ACCESS FULL TABLE MYTABLE.ORDERS Cost: 20.233.267  Bytes: 3.842  Cardinality: 113  Partition #: 7  Partitions determined by Key Values      
                                                                1 TABLE ACCESS FULL TABLE MYTABLE.CALENDAR Cost: 4  Bytes: 8  Cardinality: 1  
                                            6 PARTITION RANGE ITERATOR  Cost: 1  Cardinality: 1  Partition #: 10  Partitions determined by Key Values               
                                                   5 INDEX UNIQUE SCAN INDEX (UNIQUE) MYTABLE.BATCH_PK_IDX Cost: 1  Cardinality: 1  Partition #: 10  Partitions determined by Key Values       
                                      8 TABLE ACCESS BY LOCAL INDEX ROWID TABLE MYTABLE.BATCH Cost: 2  Bytes: 26  Cardinality: 1  Partition #: 10  Partitions accessed #1                          
                        19 NESTED LOOPS SEMI  Cost: 24  Bytes: 36  Cardinality: 1                                     
                               15 VIEW myuser. Cost: 23  Bytes: 13  Cardinality: 1                                   
                                      14 FILTER                         
                                            13 SORT GROUP BY  Cost: 23  Bytes: 20  Cardinality: 1                    
                                                   12 PARTITION RANGE ALL  Cost: 22  Bytes: 6.080  Cardinality: 304  Partition #: 17  Partitions accessed #1 - #347          
                                                          11 INDEX FAST FULL SCAN INDEX MYTABLE.RECEIVER_AVAIL_IDX Cost: 22  Bytes: 6.080  Cardinality: 304  Partition #: 17  Partitions accessed #1 - #347  
                               18 PARTITION RANGE ALL  Cost: 1  Bytes: 23  Cardinality: 1  Partition #: 19  Partitions accessed #1 - #347                               
                                      17 TABLE ACCESS BY LOCAL INDEX ROWID BATCHED TABLE MYTABLE.RECEIVER_AVAILABILITY Cost: 1  Bytes: 23  Cardinality: 1  Partition #: 19  Partitions accessed #1 - #347                     
                                            16 INDEX RANGE SCAN INDEX MYTABLE.RECEIVER_AVAIL_IDX Cost: 0  Cardinality: 1  Partition #: 19  Partitions accessed #1 - #347       

При замене вложенного запрос ключа partition_key с фактическим ключом partition_ 123: время выполнения: 6 se c

Plan
SELECT STATEMENT  ALL_ROWSCost: 234.712  Bytes: 62  Cardinality: 1                                                                           
       21 SORT AGGREGATE  Bytes: 62  Cardinality: 1                                                               
             20 NESTED LOOPS SEMI  Cost: 234.712  Bytes: 62  Cardinality: 1                                                           
                    7 NESTED LOOPS  Cost: 234.688  Bytes: 60  Cardinality: 1                                                    
                           2 PARTITION RANGE ITERATOR  Cost: 234.684  Bytes: 26  Cardinality: 1  Partition #: 4  Partitions accessed #3622 - #3623                                          
                                  1 TABLE ACCESS FULL TABLE MYTABLE.BATCH Cost: 234.684  Bytes: 26  Cardinality: 1  Partition #: 4  Partitions accessed #3622 - #3623                                      
                           6 PARTITION RANGE ITERATOR  Cost: 4  Bytes: 34  Cardinality: 1  Partition #: 6  Partitions determined by Key Values                                              
                                  5 PARTITION HASH ALL  Cost: 4  Bytes: 34  Cardinality: 1  Partition #: 7  Partitions accessed #1 - #2                                        
                                        4 TABLE ACCESS BY LOCAL INDEX ROWID BATCHED TABLE MYTABLE.ORDERS Cost: 4  Bytes: 34  Cardinality: 1  Partition #: 7  Partitions determined by Key Values                           
                                               3 INDEX RANGE SCAN INDEX MYTABLE.ORDERS_IN_FILE Cost: 2  Cardinality: 1  Partition #: 7  Partitions determined by Key Values                         
                    19 VIEW PUSHED PREDICATE VIEW SYS.VW_NSO_1 Cost: 24  Bytes: 2  Cardinality: 1                                                   
                           18 NESTED LOOPS  Cost: 24  Bytes: 36  Cardinality: 1                                                 
                                  16 NESTED LOOPS  Cost: 24  Bytes: 36  Cardinality: 1                                          
                                        13 VIEW myuser. Cost: 23  Bytes: 13  Cardinality: 1                                   
                                               12 FILTER                         
                                                      11 SORT GROUP BY  Cost: 23  Bytes: 20  Cardinality: 1                      
                                                            10 FILTER           
                                                                   9 PARTITION RANGE ALL  Cost: 22  Bytes: 6.080  Cardinality: 304  Partition #: 17  Partitions accessed #1 - #347   
                                                                          8 INDEX FAST FULL SCAN INDEX MYTABLE.RECEIVER_AVAIL_IDX Cost: 22  Bytes: 6.080  Cardinality: 304  Partition #: 17  Partitions accessed #1 - #347
                                        15 PARTITION RANGE ALL  Cost: 0  Cardinality: 1  Partition #: 19  Partitions accessed #1 - #347                               
                                               14 INDEX RANGE SCAN INDEX MYTABLE.RECEIVER_AVAIL_IDX Cost: 0  Cardinality: 1  Partition #: 19  Partitions accessed #1 - #347                       
                                  17 TABLE ACCESS BY LOCAL INDEX ROWID TABLE MYTABLE.RECEIVER_AVAILABILITY Cost: 1  Bytes: 23  Cardinality: 1  Partition #: 19  Partitions accessed #1    

Затем, что я считаю лучшим запросом: включите ключ partition_type и тип partition_type (избегая полного сканирования таблицы) : Время выполнения: 8 сек c

Plan
SELECT STATEMENT  ALL_ROWSCost: 9.611  Bytes: 100  Cardinality: 1                                                                            
       22 SORT AGGREGATE  Bytes: 100  Cardinality: 1                                                                     
             21 NESTED LOOPS SEMI  Cost: 9.611  Bytes: 100  Cardinality: 1                                                            
                    8 NESTED LOOPS  Cost: 9.587  Bytes: 98  Cardinality: 1                                                      
                           3 PARTITION RANGE SINGLE  Cost: 9.587  Bytes: 26  Cardinality: 1  Partition #: 4  Partitions accessed #3622                                          
                                  2 TABLE ACCESS BY LOCAL INDEX ROWID BATCHED TABLE MYTABLE.BATCH Cost: 9.587  Bytes: 26  Cardinality: 1  Partition #: 5  Partitions accessed #3622                                   
                                        1 INDEX SKIP SCAN INDEX (UNIQUE) MYTABLE.BATCH_PK_IDX Cost: 9.586  Cardinality: 1  Partition #: 6  Partitions accessed #3622                               
                           7 PARTITION RANGE ITERATOR  Cost: 0  Bytes: 39.384  Cardinality: 547  Partition #: 7  Partitions determined by Key Values                                              
                                  6 PARTITION HASH ALL  Cost: 0  Bytes: 39.384  Cardinality: 547  Partition #: 8  Partitions accessed #1 - #2                                  
                                        5 TABLE ACCESS BY LOCAL INDEX ROWID BATCHED TABLE MYTABLE.ORDERS Cost: 0  Bytes: 39.384  Cardinality: 547  Partition #: 8  Partitions determined by Key Values                            
                                               4 INDEX RANGE SCAN INDEX MYTABLE.ORDERS_IN_FILE Cost: 0  Cardinality: 1  Partition #: 8  Partitions determined by Key Values                         
                    20 VIEW PUSHED PREDICATE VIEW SYS.VW_NSO_1 Cost: 24  Bytes: 2  Cardinality: 1                                                   
                           19 NESTED LOOPS  Cost: 24  Bytes: 36  Cardinality: 1                                                 
                                  17 NESTED LOOPS  Cost: 24  Bytes: 36  Cardinality: 1                                          
                                        14 VIEW myuser. Cost: 23  Bytes: 13  Cardinality: 1                                   
                                               13 FILTER                         
                                                      12 SORT GROUP BY  Cost: 23  Bytes: 20  Cardinality: 1                      
                                                            11 FILTER           
                                                                   10 PARTITION RANGE ALL  Cost: 22  Bytes: 6.080  Cardinality: 304  Partition #: 18  Partitions accessed #1 - #347   
                                                                          9 INDEX FAST FULL SCAN INDEX MYTABLE.RECEIVER_AVAIL_IDX Cost: 22  Bytes: 6.080  Cardinality: 304  Partition #: 18  Partitions accessed #1 - #347
                                        16 PARTITION RANGE ALL  Cost: 0  Cardinality: 1  Partition #: 20  Partitions accessed #1 - #347                               
                                               15 INDEX RANGE SCAN INDEX MYTABLE.RECEIVER_AVAIL_IDX Cost: 0  Cardinality: 1  Partition #: 20  Partitions accessed #1 - #347                       
                                  18 TABLE ACCESS BY LOCAL INDEX ROWID TABLE MYTABLE.RECEIVER_AVAILABILITY Cost: 1  Bytes: 23  Cardinality: 1  Partition #: 20  Partitions accessed #1             

1 Ответ

0 голосов
/ 09 января 2020

Попробуйте избавиться от части раздела, так как она самая тяжелая. И я полагаю, что нет необходимости считать записи, если вам нужно только проверить, есть ли строки в таблице

select result 
from
(SELECT 1 as result
   from dual
  where not exists (select 1
                      FROM MYTABLE.ORDERS  O
                      INNER JOIN MYTABLE.CALENDAR c on c.actual_partition_key = O.PARTITION_KEY
                      INNER JOIN MYTABLE.BATCH B
                         ON  B.BATCH_ID = O.IN_BATCH_ID
                         AND B.PARTITION_KEY = O.PARTITION_KEY
                         AND B.PARTITION_TYPE = O.PARTITION_TYPE
                         AND B.INSTANCE_NUMBER = O.INSTANCE_NUMBER
                       WHERE c.is_active = 1
                         AND O.partition_type = 3 -- can leave this one out
                         AND B.START_TIME > SYSDATE - 1 / 2 / 24
                         AND B.START_TIME < SYSDATE - 10 / 60 / 24
                         AND O.STATE NOT IN ('993890', '999990')
                         AND O.RECEIVER IN (SELECT RECEIVER_ID
                                              FROM (  SELECT MAX (CREATION_DATE) AS CREATION_DATE, 
                                                             RECEIVER_ID
                                                        FROM MYTABLE.RECEIVER_AVAILABILITY
                                                    GROUP BY RECEIVER_ID) MAX_CREATION_DATE
                                              INNER JOIN MYTABLE.RECEIVER_AVAILABILITY ON MAX_CREATION_DATE.CREATION_DATE = CREATION_DATE
                                              WHERE state IN (1, 2)
                                                AND creation_date < SYSDATE - 30 / 60 / 24)
 union all 
 select 0 as result
   from dual)
order by result desc nulls last
fetch next 1 row only;

Я вижу, у вас есть разделы в БД. Это означает, что вы находитесь на корпоративной версии. Я бы порекомендовал вам использовать функцию dbms_sqltune.report_sql_monitor (sql_id) для настройки. Он покажет вам количество ожидаемых строк и количество строк, которые он получает на каждом шаге. Просто обратите внимание на шаги с наибольшей разницей

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...