Olá pessoal,

estou com dificuldade em melhorar a performance de uma query que tem
envolvida uma tabela com 30M de registros.
Com o uso do operador Minus, a query retorna em perto de 30sec. O plano de
execução fica mais complexo, utilizando varios outros indices e com custo
perto de 9800, cardinalidade 29021.

Imagino que com o Minus não seja o melhor operador para separar registros e
a query foi remodelada utilizando a clausula Exists.
Porém a performance ficou muito longe da desejada, mas o plano de execução
ficou melhor, com varios Index Range Scan, custo em 4600 e cardinalidade 1.

O resultado esperado é próximo de 5000 registros.
Segue as queries abaixo para análise e sugestões/opiniões aonde devo agir.
Agradeço desde já qquer sugestão.

Alex


- - - - - - - - -

SELECT il.item,
             il.loc,
             il.loc_type,
             il.primary_supp,
             (il.selling_unit_retail*10000) selling_unit_retail,
             il.status,
             im.dept,
             im.class,
             im.subclass
        FROM item_loc il,
 ---------------------------------->    30M registros
             item_master im,
 ----------------------------------> 54k registros
             v_restart_supplier v
       WHERE il.loc = 2836
         AND il.item = im.item
         AND im.tran_level = im.item_level
         AND il.primary_supp = v.driver_value
         AND v.driver_name = 'SUPPLIER'
         AND v.num_threads = 24
    MINUS
      SELECT f.item,
             f.loc,
       (CASE
                when (f.supplier = 3059) then
                   CASE when (f.loc < 9999000000) then 'S' else f.loc_type
END
                when (f.supplier = 3758) then
                   CASE when (f.loc < 9999000000) then 'S' else f.loc_type
END
                when (f.supplier = 3821) then
                   CASE when (f.loc < 9999000000) then 'S' else f.loc_type
END
                when (f.supplier = 4167) then
                   CASE when (f.loc < 9999000000) then 'S' else f.loc_type
END
                when (f.supplier = 4373) then
                   CASE when (f.loc < 9999000000) then 'S' else f.loc_type
END
                else
                   f.loc_type
             END) loc_type,
             f.supplier primary_supp,
             (f.retail_ctax*10000) selling_unit_retail,
             f.status,
             f.dept,
             f.class,
             f.subclass
        FROM fem_future_cost_new f,
---------------------------------------------> 173K registros
             v_restart_supplier v
       WHERE f.supplier = v.driver_value
       AND f.loc = 2836
         AND v.driver_name = 'SUPPLIER'
         AND v.num_threads = 24
       ORDER BY 4,1
;
- - - - - - - - -

 SELECT  il.item,
             il.loc,
             il.loc_type,
             il.primary_supp,
             (il.selling_unit_retail*10000) selling_unit_retail,
             il.status,
             im.dept,
             im.class,
             im.subclass
        FROM item_loc il,
             item_master im,
             v_restart_supplier v
       WHERE il.loc = 2836
         AND il.item = im.item
         AND im.tran_level = im.item_level
         AND NOT EXISTS (SELECT 1
                           FROM fem_future_cost_new f
                          WHERE f.item = il.item
                            AND f.loc = il.loc
                            AND f.supplier = il.primary_supp
                            AND f.retail_ctax = il.selling_unit_retail
                            AND f.status = il.status)
         AND il.primary_supp = v.driver_value
         AND v.driver_name = 'SUPPLIER'
         AND v.num_threads = 24
       ORDER BY 4,1
;


[As partes desta mensagem que não continham texto foram removidas]

Responder a