Oracle Sql Query занимает целый день, чтобы вернуть результаты с помощью dblink - PullRequest
0 голосов
/ 06 января 2011

Ребята, у меня есть следующий SQL-запрос оракула, который дает мне месячный отчет между датами. В основном, за ноябрь месяц я хочу сумму значений между датами от 01нов до 30 ноября.Запрашиваемая таблица находится в другой базе данных и доступна с использованием dblink.Столбцы DT имеют тип NUMBER (например, 20101201).

SELECT /*+ PARALLEL (A 8) */ /*+ DRIVING_STATE(A) */
 TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')- 1,'MM'),'MONYYYY') "MONTH", 
   TYPE AS "TYPE", COLUMN, COUNT (DISTINCT A) AS "A_COUNT",
    COUNT (COLUMN) AS NO_OF_COLS, SUM (DURATION) AS "SUM_DURATION",
     SUM (COST) AS "COST"  FROM **A@LN_PROD A**  
      WHERE DT >=  TO_NUMBER(TO_CHAR(add_months(SYSDATE,-1),'YYYYMM"01"'))
      AND  DT < TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMM"01"'))
       GROUP BY TYPE, COLUMN

Выполнение запроса занимает один день и не завершено.любезно предложите мне, если это какая-либо оптимизация, которая может быть предложена моему администратору базы данных по ссылке dblink, или любая настройка, которая может быть выполнена по запросу, или переписать то же самое.1007 *

Таблица разделена на столбцы даты и почти 1 миллиард записей.

Ниже я дал ОБЪЯСНИТЬ ПЛАН из TOAD

**Plan**
SELECT STATEMENT REMOTE  ALL_ROWSCost: 1,208,299  Bytes: 34,760  Cardinality: 790                                               
    12 PX COORDINATOR                                           
        11 PX SEND QC (RANDOM) SYS.:TQ10002 Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                                        
            10 SORT GROUP BY  Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                                      
                9 PX RECEIVE  Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                                  
                    8 PX SEND HASH SYS.:TQ10001 Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                            
                        7 SORT GROUP BY  Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                       
                            6 PX RECEIVE  Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                      
                                5 PX SEND HASH SYS.:TQ10000 Cost: 1,208,299  Bytes: 34,760  Cardinality: 790                
                                    4 SORT GROUP BY  Cost: 1,208,299  Bytes: 34,760  Cardinality: 790           
                                        3 FILTER        
                                            2 PX BLOCK ITERATOR  Cost: 1,203,067  Bytes: 15,066,833,144  Cardinality: 342,428,026  Partition #: 11  Partitions accessed #1 - #5 
                                                1 TABLE ACCESS FULL TABLE CDRR.FRD_CDF_DATA_INTL_IN_P Cost: 1,203,067  Bytes: 15,066,833,144  Cardinality: 342,428,026  Partition #: 11  

Следующие вещи, которые я собираюсь сделать сегодня, будут полезны любые дополнительные советы.

  1. Я собираюсь собрать статистические данные для этоготаблица, которая может дать оптимальный план выполнения.
  2. Проверьте, создан ли локальный индекс для раздела.
  3. , используя BETWEEN вместо> = и <. </li>

Ответы [ 3 ]

1 голос
/ 06 января 2011

Невозможно ответить, не зная структуру таблицы, ограничения, индексы, объем данных, размер набора результатов, скорость сети, уровень параллелизма, планы выполнения и так далее.

Некоторые вещи, которые я бы исследовал:

Если таблица секционирована, существует ли статистика для раздела, к которому относится запрос?Распространенной проблемой является то, что статистика собирается на пустом разделе до того, как данные были вставлены.Затем, когда вы запрашиваете его (до обновления статистики), Oracle выбирает сканирование индекса, когда на самом деле ему следует использовать FTS для этого раздела.

Также относится к статистике: убедитесь, что

WHERE DT >=TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')-1,'MM'),'YYYYMMDD')) 
  AND DT < TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM'),'MM'),'YYYYMMDD')) 

создает тот же план выполнения, что и:

WHERE DT >= 20101201
  AND DT <  20110101

Обновлено В какой версии Oracle вы работаете?Причина, по которой я спрашиваю, заключается в том, что в Oracle 10g и более поздних версиях существует другая реализация группы, которая должна быть выбрана в этом случае (хеширование, а не сортировка).Похоже, вы в основном сортируете 342 миллиона строк, возвращаемых из фильтра даты (14 гигабайт).У вас есть оперативная память, чтобы поддержать это?В противном случае вы будете выполнять многопроходную сортировку, проливая на диск.Это вероятно то, что происходит.

Согласно плану, будет возвращено около 790 строк.Это в правильном поле?Если это так, вы можете исключить сетевые проблемы:)

Кроме того, я не совсем знаком с форматом этого плана.Таблица подразделяется на разделы?В противном случае я не получу ссылку на раздел № 11.

1 голос
/ 06 января 2011

Как обычно для этого типа вопроса, план объяснения будет полезен. Это поможет нам понять, что на самом деле происходит в базе данных.

В идеале вы хотите убедиться, что запрос в удаленной базе данных выполняется, отправляя набор результатов обратно, а не отправляя данные по ссылке и выполняя запрос локально. Это гарантирует, что по ссылке будет отправлено меньше данных. В этом может помочь подсказка DRIVING_SITE, хотя Oracle обычно довольно умна в этом вопросе, поэтому может не помочь вообще.

Похоже, что Oracle лучше справляется с удаленными запросами, но проблемы все еще могут быть.

Кроме того, возможно, вам придется упростить некоторые преобразования дат.

Например, заменить это:

TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')- 1,'MM'),'MONYYYY')

с этим:

TO_CHAR(add_months(TRUNC(SYSDATE,'MM'), -1),'MONYYYY')

Возможно, он немного более эффективен, но также легче читается.

Аналогично замените это:

WHERE DT >=TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')-1,'MM'),'YYYYMMDD')) 
  AND  DT < TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM'),'MM'),'YYYYMMDD')) 

с

WHERE DT >=TO_NUMBER(TO_CHAR(add_months(TRUNC(SYSDATE,'MM'), -1),'YYYYMMDD')) 
  AND  DT < TO_NUMBER(TO_CHAR(TRUNC(SYSDATE,'MM'),'YYYYMMDD')) 

или даже

WHERE DT >=TO_NUMBER(TO_CHAR(add_months(SYSDATE,-1),'YYYYMM"01"')) 
  AND  DT < TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMM"01"')) 
1 голос
/ 06 января 2011

Это может быть связано с несколькими проблемами: 1. Скорость сети, поскольку база данных может находиться на другом оборудовании.Однако вы можете обратиться по этой ссылке http://www.experts -exchange.com / База данных / Oracle / Q_21799513.html .Есть похожая проблема.

...