2014-11-17 4 views
0

У меня есть следующий запрос, который я пытаюсь оптимизировать, запрос выполняется за 3 секунды, если я удалю условие соединения I.ident_id в (выберите отдельный (ident_id) из MISSING_Images miss) из ниже запроса но с этим я занимаю 3 минуты, чтобы выполнить.Медленный запрос с несколькими объединениями

SELECT IDENT_ID 
    FROM tbl_IDENT I 
      JOIN tbl_TA AN ON (AN.IDENT_ID = I.IDENT_ID and AN.anchor_point = I.c_id) 
      JOIN tbl_AB A ON (A.A_ID = I.A_ID) 
      JOIN tbl_FULL_ARCHIVE FT ON (FT.ARCHIVE_ID = I.ARCHIVE_ID) 
      WHERE (I.DATA_STATUS = 'ACTIVE' or I.DATA_STATUS = 'INACTIVE') 
      AND 
      (
      I.FD = 'Y' 
       OR 


I.ident_id in (select distinct(ident_id) from MISSING_Images miss where substr(miss.NAME, 0, INSTR(miss.NAME, '.',-1,1)) in (SELECT substr(IMG_NAME, 0, INSTR(IMG_NAME, '.',-1,1)) FROM IMAGES)) 

);

выбрать отличный (ident_id) от MISSING_Images miss возвращение 2000 записей и основной tbl_IDENT имеет более 100 000 записей. У меня есть индекс, созданный на I.ident_id

Любой намек на его улучшение. Я использую оракул 10g.

ответ

2

Вы можете попробовать заменить

I.ident_id in (select distinct(ident_id) from MISSING_Images miss) 

с

EXISTS (select 1 from MISSING_Images miss where miss.ident_id = I.ident_id) 

И создать индекс на MISSING_Images.ident_id

EDIT: самое прямое решение будет:

EXISTS (select 1 from MISSING_Images miss 
     where miss.ident_id = I.ident_id 
      and exists (select 1 from images img 
         where substr(img.IMG_NAME, 0, INSTR(img.IMG_NAME, '.',-1,1)) 
          = substr(miss,NAME, 0, INSTR(IMG_NAME, '.',-1,1)) 
        ) 
     ) 

И создать индекс на основе индексов:

create index indx_name1 on images(substr(IMG_NAME, 0, INSTR(IMG_NAME, '.',-1,1))); 
create index indx_name2 on MISSING_Images(substr(miss.NAME, 0, INSTR(miss.NAME, '.',-1,1))); 

Принять к сведению, что такие показатели могут иметь плохие последствия для вставки/обновления операции над незатухающими объектами и требуют дополнительного пространства. Кроме того, они не работают с нулями.

Другие варианты:

EXISTS (select 1 from MISSING_Images miss join images img 
         on substr(img.IMG_NAME, 0, INSTR(img.IMG_NAME, '.',-1,1)) 
          = substr(miss,NAME, 0, INSTR(IMG_NAME, '.',-1,1)) 
     where miss.ident_id = I.ident_id 
     ) 


EXISTS (select 1 from (select miss.ident_id MISSING_Images miss join images img 
         on substr(img.IMG_NAME, 0, INSTR(img.IMG_NAME, '.',-1,1)) 
          = substr(miss,NAME, 0, INSTR(IMG_NAME, '.',-1,1)) 
         ) sub   
     where sub.ident_id = I.ident_id 
     ) 
+0

Я видел несколько тестов в DB2, где «EXISTS» работает лучше, чем «IN», поэтому меня не удивит то же самое, что и в Oracle.Тем не менее, если у вас нет индекса на MISSING_Images.ident_id, создание этого индекса приведет к значительному улучшению. –

+0

Привет, Майк, с индексом MISSING_Images.ident_id, но я обновил этот вопрос, потому что забыл добавить предложение where в MISSING_Images, которое использует substr, и это кажется реальной проблемой. – atif

+0

@atif Сколько у вас изображений? Есть ли возможность сохранить внешний ключ в IMAGES в MISSING_Images вместо разбора и сравнения имен? – Multisync

1

Попробуйте союз вместо этого, для начала?

SELECT IDENT_ID 
FROM tbl_IDENT I 
    JOIN tbl_TA AN ON AN.IDENT_ID = I.IDENT_ID AND AN.anchor_point = I.c_id 
    JOIN tbl_AB A ON A.A_ID = I.A_ID 
    JOIN tbl_FULL_ARCHIVE FT ON FT.ARCHIVE_ID = I.ARCHIVE_ID 
WHERE 
    (I.DATA_STATUS = 'ACTIVE' OR I.DATA_STATUS = 'INACTIVE') 
AND I.FD = 'Y' 
UNION 
SELECT IDENT_ID 
FROM tbl_IDENT I 
    JOIN tbl_TA AN ON AN.IDENT_ID = I.IDENT_ID AND AN.anchor_point = I.c_id 
    JOIN tbl_AB A ON A.A_ID = I.A_ID 
    JOIN tbl_FULL_ARCHIVE FT ON FT.ARCHIVE_ID = I.ARCHIVE_ID 
    JOIN MISSING_Images miss ON I.ident_id = miss.ident_id 
WHERE 
    I.DATA_STATUS = 'ACTIVE' 
OR I.DATA_STATUS = 'INACTIVE' 
; 

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

1

Создать индекс на MISSING_Images(ident_id).

Я также хотел бы предложить, что вы пишете статью where как:

 WHERE I.DATA_STATUS IN ('ACTIVE', 'INACTIVE') AND 
       (I.FD = 'Y' OR 
       I.ident_id in (select ident_id from MISSING_Images miss) 
      ) 

distinct ненужно в in подзапроса. Кроме того, in легче читать (и писать и обслуживать), затем список отдельных сравнений. Индекс должен заботиться о производительности.

0

вы даже можете комбинировать фильтры, где это в условиях присоединиться как ниже

SELECT IDENT_ID 
    FROM tbl_IDENT I 
      JOIN tbl_TA AN ON (AN.IDENT_ID = I.IDENT_ID and AN.anchor_point = I.c_id) 
      and I.DATA_STATUS IN ('ACTIVE', 'INACTIVE') AND 
      I.FD = 'Y' 
       OR 
      I.ident_id in (select distinct(ident_id) from MISSING_Images miss) 
      JOIN tbl_AB A ON (A.A_ID = I.A_ID) 
      JOIN tbl_FULL_ARCHIVE FT ON (FT.ARCHIVE_ID = I.ARCHIVE_ID); 

и даже вы можете иметь такое положение с этим (как сказал @Multisync) может привести к более высокой производительности.

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