2013-08-15 4 views
0
select round(avg(et_gsm_sınyal)) as sinyal,mahalle_kodu,ilce_kodu,sebeke 
from 
    (select et_gsm_sınyal,sozlesme_no,SUBSTR(et_operator,1,5) as sebeke 
    from thkol316old 
    where tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1) 
    AND tarih < TRUNC(SYSDATE, 'MM')) okuma, 
    (select sozlesme_no,ilce_kodu,mahalle_kodu from commt020) bilgiler 
where okuma.sozlesme_no=bilgiler.sozlesme_no 
group by mahalle_kodu,ilce_kodu,sebeke; 
  • commt020 -> клиент таблица
  • thkol316old -> старый законопроект стол

Этот запрос работает, но это работает очень медленно.Oracle Query SQL Tuning?

Это примерно 550 секунд времени отклика.

Что должен сделать этот запрос быстрее?

Это план выполнения

SELECT STATEMENT 7547   

HASH 
    GROUP BY 7547   

FILTER 


Filter Predicates 

ADD_MONTHS(TRUNC([email protected]!,'fmmm'),-1) 

NESTED LOOPS 


NESTED LOOPS 
     7546   

TABLE ACCESS 
COMMT020 BY GLOBAL INDEX ROWID 3 ROW LOCATION ROW LOCATION` 
+3

Ответ №1: Проверить план выполнения. Затем выполните соответствующие действия ... (Чтобы получить план выполнения, нажмите F10 в разработчике SQL, как вы упомянули, используя это) – ppeterka

+0

Я пробовал, но я не понимаю, что я должен делать? Стоимость составляет 7547 – ofince

+0

Не общая стоимость важна, а как суммируются дополнительные затраты. Вы также можете вставить текст здесь ... Кроме того, вы можете проверить дерево, часть, которая является высокой стоимостью, означает, что есть медлительность ... – ppeterka

ответ

0

Прежде всего я хотел бы попробовать с обычным столом присоединяется вместо более неудобного зрения инлайн - присоединение, я надеюсь, что следующее будет работать (я не создал таблицы и пытался он):

select round(avg(okuma.et_gsm_sınyal)) as sinyal, 
bilgiler.mahalle_kodu,bilgiler.ilce_kodu, SUBSTR(okuma.et_operator,1,5) as sebeke 
from thkol316old okuma 
inner join commt020 bilgiler on okuma.sozlesme_no=bilgiler.sozlesme_no 
where okuma.tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1) 
AND okuma.tarih < TRUNC(SYSDATE, 'MM') 
group by bilgiler.mahalle_kodu,bilgiler.ilce_kodu, SUBSTR(okuma.et_operator,1,5); 

Тогда, если все еще медленно:

  1. Убедитесь, что есть индекс, где bilgiler.sozlesme_no является первый столбец в индексе
  2. Убедитесь, что существует индекс, где okuma.sozlesme_no первый столбец в индексе
  3. Убедитесь, что существует индекс, где okuma.tarih первый столбец в индекс
0

Ясно

колонка Tarih не индексируется для таблицы thkol316old

create index tarih_idx on thkol316old (tarih);

Тогда

analyze table commt020 compute statistics;
analyze table thkol316old compute statistics;

В Oracle анализирующих таблиц производят информацию, которая используется при создании планов выполнения запросов. Каждый раз, когда вы меняете таблицу, вы также можете ее проанализировать. Многие крупные системы делают это по графику.

+3

Таблица анализа устарела для сбора статистики. Вместо этого используйте DBMS_Stats. –

+2

Возможно, правильно в этой ситуации, судя по характеру используемой таблицы, но будьте осторожны, прыгая прямо на добавление индекса без информации о том, насколько избирателен фильтр предикатов и как данные фактически выложены в таблице. Опять же, это, вероятно, подходит для этого примера, но OP должен знать, что попытка решить проблемы с производительностью, просто добавив больше индексов, не исследуя, насколько они помогут, - это ужасная привычка. – Craig

+0

+1 для Дэвида и Крейга –

0

Прежде всего, вам не нужен BILIGILER встроенного вида просто выбрать несколько столбцов из таблицы COMMT020, вы будете прекрасно выбирающей из этой таблицы непосредственно:

SELECT ROUND(AVG(et_gsm_s1nyal)) AS sinyal, 
     mahalle_kodu,ilce_kodu,sebeke 
FROM (
    SELECT et_gsm_s1nyal, 
      sozlesme_no, 
      SUBSTR(et_operator,1,5) AS sebeke 
    FROM thkol316old 
    WHERE tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1) 
    AND tarih < TRUNC(SYSDATE, 'MM') 
    ) okuma, commt020  
WHERE okuma.sozlesme_no = commt020.sozlesme_no 
GROUP BY mahalle_kodu,ilce_kodu,sebeke 
/

Тогда, давайте перепишем join, используя выражение ANSI join. Я предпочитаю, чтобы ANSI присоединяется к старым объединениям в стиле Oracle, потому что они позволяют отделить условия соединения от условий фильтрации, тем самым обеспечивая большую ясность в том, что происходит на самом деле. Кроме того, это хороший стиль для назначения псевдонимов таблицам и четкое указание, какие столбцы мы выбираем из этой таблицы.

SELECT ROUND(AVG(o.et_gsm_s1nyal)) AS sinyal, 
     c.mahalle_kodu, c.ilce_kodu, o.sebeke 
FROM (
    SELECT th.et_gsm_s1nyal, 
      th.sozlesme_no, 
      SUBSTR(th.et_operator,1,5) AS sebeke 
    FROM thkol316old th 
    WHERE th.tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1) 
    AND th.tarih < TRUNC(SYSDATE, 'MM') 
    ) okuma o 
JOIN commt020 c ON o.sozlesme_no = c.sozlesme_no 
GROUP BY c.mahalle_kodu, c.ilce_kodu, o.sebeke 
/

Теперь оно яснее, чем остальное встроенное изображение избыточно.Несмотря на то, что трудно сказать, не зная подробностей этих таблиц, но вы, вероятно, будет лучше «разворачивает», что вложенное представление и заменить его прямой присоединиться:

SELECT ROUND(AVG(th.et_gsm_s1nyal)) AS sinyal, 
     c.mahalle_kodu, 
     c.ilce_kodu, 
     SUBSTR(th.et_operator,1,5) AS sebeke 
FROM commt020 c 
JOIN thkol316old th ON c.sozlesme_no = th.sozlesme_no 
WHERE th.tarih >= ADD_MONTHS (TRUNC (SYSDATE, 'MM'), -1) 
AND th.tarih < TRUNC(SYSDATE, 'MM') 
GROUP BY c.mahalle_kodu, c.ilce_kodu, SUBSTR(th.et_operator,1,5) 
/

К сожалению оптимизации этого запроса дополнительно требует дополнительной информации, таких как:

  • Новый план выполнения.
  • Версия Oracle, которую вы используете.
  • Число строк в таблицах THKOL316OLD и COMMT020.
  • Какие индексы существуют на этих таблицах.