2016-11-24 3 views
0

Я относительно новичок в SQL. У меня есть сценарий, который работал очень быстро (< 0,5 секунды), но работает очень медленно (> 120 секунд), если я добавлю одно изменение - и я не понимаю, почему это изменение имеет такое значение. Любая помощь была бы чрезвычайно оценена!SQL-скрипт работает очень медленно с небольшим изменением

Это сценарий, и он работает быстро, если я не включаю «tt2.bulk_cnt » в строке 26:

with bulksum1 as 
(
select t1.membercode, 
     t1.schemecode, 
     t1.transdate 
from mina_raw2 t1 
where t1.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS') 
group by t1.membercode, 
      t1.schemecode, 
      t1.transdate 
), 

bulksum2 as 
(
select t1.schemecode, 
     t1.transdate, 
     count(*) as bulk_cnt 
from bulksum1 t1 
group by t1.schemecode, 
      t1.transdate 
having count(*) >= 10 
), 

results as 
(
select t1.*, tt2.bulk_cnt 
from mina_raw2 t1 
inner join bulksum2 tt2 
on t1.schemecode = tt2.schemecode and t1.transdate = tt2.transdate 
where t1.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS') 
) 

select * from results 

EDIT: Я извиняюсь за не прикладывая достаточно подробно здесь ранее - хотя я могу используйте базовый код SQL, я полный новичок, когда дело доходит до баз данных.

База данных: Oracle (я не уверен, какая версия, извините)

планов выполнения:

БЫСТРЫЙ запрос:

Plan hash value: 1712123489 

--------------------------------------------- 
| Id | Operation    | Name  | 
--------------------------------------------- 
| 0 | SELECT STATEMENT  |   | 
| 1 | HASH JOIN    |   | 
| 2 | VIEW     |   | 
| 3 | FILTER    |   | 
| 4 |  HASH GROUP BY  |   | 
| 5 |  VIEW    | VM_NWVW_0 | 
| 6 |  HASH GROUP BY  |   | 
| 7 |  TABLE ACCESS FULL| MINA_RAW2 | 
| 8 | TABLE ACCESS FULL  | MINA_RAW2 | 
--------------------------------------------- 

SLOW запрос:

Plan hash value: 1298175315 

-------------------------------------------- 
| Id | Operation    | Name  | 
-------------------------------------------- 
| 0 | SELECT STATEMENT  |   | 
| 1 | FILTER    |   | 
| 2 | HASH GROUP BY  |   | 
| 3 | HASH JOIN   |   | 
| 4 |  VIEW    | VM_NWVW_0 | 
| 5 |  HASH GROUP BY  |   | 
| 6 |  TABLE ACCESS FULL| MINA_RAW2 | 
| 7 |  TABLE ACCESS FULL | MINA_RAW2 | 
-------------------------------------------- 
+0

Какая платформа базы данных? – OldProgrammer

+1

Вы присоединяетесь к индексированным полям? –

+2

Вы сравнили план выполнения для двух запросов? – CodeReaper

ответ

0

Несколько наблюдений, а затем некоторые вещи, чтобы сделать: необходимо

1) Более подробная информация. В частности, сколько строк в таблице MINA_RAW2, какие индексы существуют в этой таблице, и когда последний раз он анализировался? Для того, чтобы определить, ответы на эти вопросы, запустите:

SELECT COUNT(*) FROM MINA_RAW2; 

SELECT TABLE_NAME, LAST_ANALYZED, NUM_ROWS 
    FROM USER_TABLES 
    WHERE TABLE_NAME = 'MINA_RAW2'; 

Глядя на выходе плана он выглядит как база данных делает два полных сканирований MINA_RAW2 - это было бы хорошо, если бы это можно было бы сократить до не более чем один , и, надеюсь, нет. Всегда трудно описать без подробной информации о данных в таблице, но сначала краснеть, кажется, что индекс в TRANSACTIONTYPE может оказаться полезным. Если такой индекс не существует, вы можете захотеть его добавить.

2) Предполагая, что статистика устарела (как в, старая, несуществующая или значительная сумма данных (> 10%) была добавлена, удалена или обновлена ​​со времени последнего анализа), запустите следующие:

BEGIN 
    DBMS_STATS.GATHER_TABLE_STATS(owner => 'YOUR-SCHEMA-NAME', 
           table_name => 'MINA_RAW2'); 
END; 

Подставляя правильное название схемы для «ВАШЕ-ШЕМ-НАЗВАНИЕ» выше. Не забудьте использовать название схемы! Если вы не знаете, следует ли вам собирать статистику или не собирать статистические данные, сделайте ошибку на стороне осторожности и сделайте это. Это не займет много времени.

3) Повторите попытку существующего запроса после обновления статистики таблицы. Я думаю, что есть вероятность, что наличие актуальной статистики в базе данных позволит решить ваши проблемы. Если нет:

4) Этот запрос выполняет GROUP BY по результатам GROUP BY.Это не кажется необходимым, поскольку начальная группа GROUP BY не делает никакой группировки - вместо этого, похоже, это делается для получения уникальных комбинаций MEMBERCODE, SCHEMECODE и TRANSDATE, чтобы подсчет членов по схеме и дата может быть определена. Я думаю, что весь запрос можно упростить до:

WITH cteWORKING_TRANS AS (SELECT * 
          FROM MINA_RAW2 
          WHERE TRANSACTIONTYPE IN ('RSP','SP','UNTV', 
                 'ASTR','CN','TVIN', 
                 'UCON','TRAS')), 
    cteBULKSUM AS (SELECT a.SCHEMECODE, 
          a.TRANSDATE, 
          COUNT(*) AS BULK_CNT 
         FROM (SELECT DISTINCT MEMBERCODE, 
              SCHEMECODE, 
              TRANSDATE 
           FROM cteWORKING_TRANS) a 
         GROUP BY a.SCHEMECODE, 
           a.TRANSDATE) 
SELECT t.*, b.BULK_CNT 
    FROM cteWORKING_TRANS t 
    INNER JOIN cteBULKSUM b 
    ON b.SCHEMECODE = t.SCHEMECODE AND 
     b.TRANSDATE = t.TRANSDATE 
+0

Анализ таблицы, казалось, сделал трюк - запрос теперь выполняется очень быстро. Также ваш пересмотренный запрос имеет гораздо больший смысл. Большое спасибо за вашу помощь - это очень ценится! – Nick

0

I удалось удалить ненужный подзапрос, но этот синтаксис с distinct внутри count может не работать вне PostgreSQL или не может быть желаемым результатом. Я знаю, что я определенно использовал его там.

select t1.*, tt2.bulk_cnt 
from mina_raw2 t1 
inner join (select t2.schemecode, 
     t2.transdate, 
     count(DISTINCT membercode) as bulk_cnt 
from mina_raw2 t2 
where t2.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS') 
group by t2.schemecode, 
      t2.transdate 
having count(DISTINCT membercode) >= 10) tt2 
on t1.schemecode = tt2.schemecode and t1.transdate = tt2.transdate 
where t1.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS') 

При использовании этих with запросов, вместо подзапросов, когда вам не нужно, вы kneecapping оптимизатор запросов.

+0

Спасибо за это (это, безусловно, выглядит намного лучше, чем моя попытка), но он по-прежнему работает очень медленно. – Nick

Смежные вопросы