简体   繁体   中英

performance query issue - Oracle

I have two views, v_movimiento_no_duplicado and v_personas_no_duplicadas . Both queries removes duplicates from tables CLM020A and CLM010A respectively. When i execute each query individually i get fast return, when i join them is fast too. Problem is when i put some predicates, for example:

SELECT *
  FROM v_movimiento_no_duplicado
       INNER JOIN v_personas_no_duplicadas USING (cedula_rel)
 WHERE     LENGTH (nombres_010) <= 30
       AND LENGTH (apellidos_010) <= 30
       --AND LENGTH (cedula_rel) <= 15;

Without last predicate takes 125 ms(is ok),but if add third predicate takes 11 seconds. I haven't indexes at this moment, but i have tried indexes for each of three colums, composites indexes even function-based indexes, but result is the same or worst. This are the plans for both cases:

With two predicates (faster):

-------------------------------------------------------------------------------------
| Id  | Operation                | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |          |    27 |  7371 |   253   (2)| 00:00:04 |
|*  1 |  HASH JOIN               |          |    27 |  7371 |   253   (2)| 00:00:04 |
|*  2 |   HASH JOIN              |          |    27 |  7047 |   149   (3)| 00:00:02 |
|*  3 |    HASH JOIN SEMI        |          |    14 |  1596 |    46   (5)| 00:00:01 |
|   4 |     JOIN FILTER CREATE   | :BF0000  |    14 |  1148 |    22   (0)| 00:00:01 |
|*  5 |      TABLE ACCESS FULL   | CLM010A  |    14 |  1148 |    22   (0)| 00:00:01 |
|   6 |     VIEW                 | VW_NSO_1 |    56 |  1792 |    23   (5)| 00:00:01 |
|*  7 |      FILTER              |          |       |       |            |          |
|   8 |       HASH GROUP BY      |          |     1 |   672 |    23   (5)| 00:00:01 |
|   9 |        JOIN FILTER USE   | :BF0000  |  5532 | 66384 |    22   (0)| 00:00:01 |
|* 10 |         TABLE ACCESS FULL| CLM010A  |  5532 | 66384 |    22   (0)| 00:00:01 |
|  11 |    TABLE ACCESS FULL     | CLM020A  | 10734 |  1540K|   102   (0)| 00:00:02 |
|  12 |   VIEW                   | VW_NSO_2 | 10734 |   125K|   104   (2)| 00:00:02 |
|  13 |    HASH GROUP BY         |          | 10734 |   461K|   104   (2)| 00:00:02 |
|* 14 |     TABLE ACCESS FULL    | CLM020A  | 10734 |   461K|   102   (0)| 00:00:02 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("M".ROWID="FILA")
   2 - access("CEDULA_REL"="CEDULA_REL")
   3 - access("CEDULA_REL"="CEDULA_REL")
   5 - filter(LENGTH("NOMBRES_010")<=30 AND LENGTH("APELLIDOS_010")<=30)
   7 - filter(COUNT("CEDULA_REL")=1)
  10 - filter(SYS_OP_BLOOM_FILTER(:BF0000,"CEDULA_REL"))
  14 - filter(("M"."TIPO_020"='E' OR "M"."TIPO_020"='S') AND 
              "M"."LUGARMOV_020" IS NOT NULL)

Now, with three predicates (slower):

--------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |         |     1 |   229 |   252   (2)| 00:00:04 |
|*  1 |  FILTER              |         |       |       |            |          |
|*  2 |   HASH JOIN          |         |     1 |   229 |   125   (1)| 00:00:02 |
|*  3 |    TABLE ACCESS FULL | CLM010A |     1 |    82 |    22   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL | CLM020A | 10734 |  1540K|   102   (0)| 00:00:02 |
|*  5 |   FILTER             |         |       |       |            |          |
|   6 |    HASH GROUP BY     |         |     1 |    12 |    23   (5)| 00:00:01 |
|   7 |     TABLE ACCESS FULL| CLM010A |  5532 | 66384 |    22   (0)| 00:00:01 |
|*  8 |   FILTER             |         |       |       |            |          |
|   9 |    HASH GROUP BY     |         |   108 |  4752 |   104   (2)| 00:00:02 |
|* 10 |     TABLE ACCESS FULL| CLM020A | 10734 |   461K|   102   (0)| 00:00:02 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter( EXISTS (SELECT 0 FROM "LIMOV"."CLM010A" "P2" GROUP BY 
              "CEDULA_REL" HAVING "CEDULA_REL"=:B1 AND COUNT("CEDULA_REL")=1) AND  
              EXISTS (SELECT 0 FROM "LIMOV"."CLM020A" "M" WHERE ("M"."TIPO_020"='E' 
              OR "M"."TIPO_020"='S') AND "M"."LUGARMOV_020" IS NOT NULL GROUP BY 
              UPPER(TRIM("M"."LUGARMOV_020"))||UPPER("M"."TIPO_020")||TO_CHAR(INTERNAL
              _FUNCTION("M"."FECHA_020"),'YYYYMMDDHH24MI')||"M"."CEDULA_REL" HAVING 
              MAX("M".ROWID)=:B2))
   2 - access("CEDULA_REL"="CEDULA_REL")
   3 - filter(LENGTH("NOMBRES_010")<=30 AND LENGTH("APELLIDOS_010")<=30 
              AND LENGTH("CEDULA_REL")<=15)
   5 - filter("CEDULA_REL"=:B1 AND COUNT("CEDULA_REL")=1)
   8 - filter(MAX("M".ROWID)=:B1)
  10 - filter(("M"."TIPO_020"='E' OR "M"."TIPO_020"='S') AND 
              "M"."LUGARMOV_020" IS NOT NULL)

As you can see both plans are differents. I haven't much experience working with plans, any help will be appreciated.

--VIEWS

   CREATE VIEW V_MOVIMIENTO_NO_DUPLICADO SELECT "CEDULA_REL",
          "TIPO_020",
          "FECHA_020",
          "LUGARMOV_020",
          "CLM_020",
          "TRASLADO_020",
          "RESPALDADO",
          "ESTADIA",
          "DIRECCION",
          "FECHA_LETRA",
          "HORA_SERVER",
          "USUARIO"
     FROM movimiento m
    WHERE m.ROWID IN (  SELECT MAX (m.ROWID) fila
                          FROM movimiento m
                         WHERE     M.lugarmov_020 IS NOT NULL
                               AND M.tipo_020 IN ('E', 'S')
                      GROUP BY    UPPER (TRIM (M.lugarmov_020))
                               || UPPER (M.tipo_020)
                               || TO_CHAR (M.fecha_020, 'YYYYMMDDHH24MI')
                               || M.CEDULA_REL)

CREATE VIEW V_PERSONAS_NO_DUPLICADAS SELECT CEDULA_REL,
          NOMBRES_010,
          APELLIDOS_010,
          FECHANAC_010,
          NACIONALIDAD_010,
          TVIAJERO_010,
          RESPALDADO,
          RESIDENCIA,
          SEXO,
          FREGISTRO,
          PC,
          USUARIO,
          USERUPDATE,
          DATEUPDATE
     FROM persona P1
    WHERE cedula_rel IN (  SELECT cedula_rel
                             FROM persona P2
                         GROUP BY cedula_rel
                           HAVING COUNT (cedula_rel) = 1)

--Plans after indexes were added:

Fastest Query: (taking 12 secs more)

    ---------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                  |     1 |   261 |   133   (4)| 00:00:02 |
|   1 |  NESTED LOOPS                  |                  |       |       |            |          |
|   2 |   NESTED LOOPS                 |                  |     1 |   261 |    29   (7)| 00:00:01 |
|   3 |    NESTED LOOPS                |                  |     1 |   114 |    26   (8)| 00:00:01 |
|   4 |     VIEW                       | VW_NSO_1         |    56 |  1792 |    23   (5)| 00:00:01 |
|*  5 |      FILTER                    |                  |       |       |            |          |
|   6 |       HASH GROUP BY            |                  |     1 |   672 |    23   (5)| 00:00:01 |
|   7 |        TABLE ACCESS FULL       | CLM010A          |  5532 | 66384 |    22   (0)| 00:00:01 |
|*  8 |     TABLE ACCESS BY INDEX ROWID| CLM010A          |     1 |    82 |     2   (0)| 00:00:01 |
|*  9 |      INDEX RANGE SCAN          | IDX_CEDULA_REL   |     1 |       |     1   (0)| 00:00:01 |
|* 10 |    INDEX RANGE SCAN            | IDX_CEDULA_REL_2 |     2 |       |     1   (0)| 00:00:01 |
|* 11 |     FILTER                     |                  |       |       |            |          |
|  12 |      HASH GROUP BY             |                  |   108 |  4752 |   104   (2)| 00:00:02 |
|* 13 |       TABLE ACCESS FULL        | CLM020A          | 10734 |   461K|   102   (0)| 00:00:02 |
|  14 |   TABLE ACCESS BY INDEX ROWID  | CLM020A          |     1 |   147 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - filter(COUNT("CEDULA_REL")=1)
   8 - filter(LENGTH("NOMBRES_010")<=30)
   9 - access("CEDULA_REL"="CEDULA_REL")
       filter(LENGTH("CEDULA_REL")<=15)
  10 - access("CEDULA_REL"="CEDULA_REL")
       filter( EXISTS (SELECT 0 FROM "LIMOV"."CLM020A" "M" WHERE ("M"."TIPO_020"='E' OR 
              "M"."TIPO_020"='S') AND "M"."LUGARMOV_020" IS NOT NULL GROUP BY 
              UPPER(TRIM("M"."LUGARMOV_020"))||UPPER("M"."TIPO_020")||TO_CHAR(INTERNAL_FUNCTION("M"."FECH
              A_020"),'YYYYMMDDHH24MI')||"M"."CEDULA_REL" HAVING MAX("M".ROWID)=:B1))
  11 - filter(MAX("M".ROWID)=:B1)
  13 - filter(("M"."TIPO_020"='E' OR "M"."TIPO_020"='S') AND "M"."LUGARMOV_020" IS NOT 
              NULL)

Slowest Query: (canceled at 2 mins)

-----------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |                  |     1 |   241 |   116   (3)| 00:00:02 |
|*  1 |  FILTER                          |                  |       |       |            |          |
|   2 |   HASH GROUP BY                  |                  |     1 |   241 |   116   (3)| 00:00:02 |
|   3 |    NESTED LOOPS                  |                  |       |       |            |          |
|   4 |     NESTED LOOPS                 |                  |     1 |   241 |    11   (0)| 00:00:01 |
|   5 |      NESTED LOOPS                |                  |     1 |    94 |     8   (0)| 00:00:01 |
|*  6 |       TABLE ACCESS BY INDEX ROWID| CLM010A          |     1 |    82 |     7   (0)| 00:00:01 |
|*  7 |        INDEX RANGE SCAN          | IDX_CEDULA_LEN   |    50 |       |     2   (0)| 00:00:01 |
|*  8 |       INDEX RANGE SCAN           | IDX_CEDULA_REL   |     1 |    12 |     1   (0)| 00:00:01 |
|*  9 |      INDEX RANGE SCAN            | IDX_CEDULA_REL_2 |     2 |       |     1   (0)| 00:00:01 |
|* 10 |       FILTER                     |                  |       |       |            |          |
|  11 |        HASH GROUP BY             |                  |   108 |  4752 |   104   (2)| 00:00:02 |
|* 12 |         TABLE ACCESS FULL        | CLM020A          | 10734 |   461K|   102   (0)| 00:00:02 |
|  13 |     TABLE ACCESS BY INDEX ROWID  | CLM020A          |     1 |   147 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(COUNT("CEDULA_REL")=1)
   6 - filter(LENGTH("NOMBRES_010")<=30 AND LENGTH("APELLIDOS_010")<=30)
   7 - access(LENGTH("CEDULA_REL")<=15)
   8 - access("CEDULA_REL"="CEDULA_REL")
   9 - access("CEDULA_REL"="CEDULA_REL")
       filter( EXISTS (SELECT 0 FROM "LIMOV"."CLM020A" "M" WHERE ("M"."TIPO_020"='E' OR 
              "M"."TIPO_020"='S') AND "M"."LUGARMOV_020" IS NOT NULL GROUP BY 
              UPPER(TRIM("M"."LUGARMOV_020"))||UPPER("M"."TIPO_020")||TO_CHAR(INTERNAL_FUNCTION("M"."FECHA_
              020"),'YYYYMMDDHH24MI')||"M"."CEDULA_REL" HAVING MAX("M".ROWID)=:B1))
  10 - filter(MAX("M".ROWID)=:B1)
  12 - filter(("M"."TIPO_020"='E' OR "M"."TIPO_020"='S') AND "M"."LUGARMOV_020" IS NOT NULL)

I solved the problem changing the order of the views in the join, then the execution plan changes, and filters changes drastically.

Slowest query:

SELECT *
  FROM v_movimiento_no_duplicado
       INNER JOIN v_personas_no_duplicadas USING (cedula_rel)
 WHERE     LENGTH (nombres_010) <= 30
       AND LENGTH (apellidos_010) <= 30
       AND LENGTH (cedula_rel) <= 15;

--------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |         |     1 |   229 |   252   (2)| 00:00:04 |
|*  1 |  FILTER              |         |       |       |            |          |
|*  2 |   HASH JOIN          |         |     1 |   229 |   125   (1)| 00:00:02 |
|*  3 |    TABLE ACCESS FULL | CLM010A |     1 |    82 |    22   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL | CLM020A | 10734 |  1540K|   102   (0)| 00:00:02 |
|*  5 |   FILTER             |         |       |       |            |          |
|   6 |    HASH GROUP BY     |         |     1 |    12 |    23   (5)| 00:00:01 |
|   7 |     TABLE ACCESS FULL| CLM010A |  5532 | 66384 |    22   (0)| 00:00:01 |
|*  8 |   FILTER             |         |       |       |            |          |
|   9 |    HASH GROUP BY     |         |   108 |  4752 |   104   (2)| 00:00:02 |
|* 10 |     TABLE ACCESS FULL| CLM020A | 10734 |   461K|   102   (0)| 00:00:02 |
--------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - filter( EXISTS (SELECT 0 FROM "LIMOV"."CLM010A" "P2" GROUP BY
"CEDULA_REL" HAVING "CEDULA_REL"=:B1 AND COUNT("CEDULA_REL")=1) AND
EXISTS (SELECT 0 FROM "LIMOV"."CLM020A" "M" WHERE ("M"."TIPO_020"='E'
OR "M"."TIPO_020"='S') AND "M"."LUGARMOV_020" IS NOT NULL GROUP BY
UPPER(TRIM("M"."LUGARMOV_020"))||UPPER("M"."TIPO_020")||TO_CHAR(INTERNAL
_FUNCTION("M"."FECHA_020"),'YYYYMMDDHH24MI')||"M"."CEDULA_REL" HAVING
MAX("M".ROWID)=:B2))
2 - access("CEDULA_REL"="CEDULA_REL")
3 - filter(LENGTH("NOMBRES_010")<=30 AND LENGTH("APELLIDOS_010")<=30
AND LENGTH("CEDULA_REL")<=15)
5 - filter("CEDULA_REL"=:B1 AND COUNT("CEDULA_REL")=1)
8 - filter(MAX("M".ROWID)=:B1)
10 - filter(("M"."TIPO_020"='E' OR "M"."TIPO_020"='S') AND
"M"."LUGARMOV_020" IS NOT NULL)

Check that filter 1 looks to be a bit expensive. When i changed the order of views it just disappear.

SELECT *
  FROM v_personas_no_duplicadas
       INNER JOIN v_movimiento_no_duplicado USING (cedula_rel)
 WHERE    LENGTH (nombres_010) <= 30
       AND LENGTH (apellidos_010) <= 30
       AND LENGTH (cedula_rel) <= 15;

----------------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |    14 |  3822 |   253   (2)| 00:00:04 |
|*  1 |  HASH JOIN SEMI       |          |    14 |  3822 |   253   (2)| 00:00:04 |
|*  2 |   HASH JOIN           |          |    14 |  3374 |   229   (2)| 00:00:03 |
|*  3 |    HASH JOIN          |          |    14 |  3206 |   125   (1)| 00:00:02 |
|*  4 |     TABLE ACCESS FULL | CLM010A  |    14 |  1148 |    22   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL | CLM020A  |   537 | 78939 |   102   (0)| 00:00:02 |
|   6 |    VIEW               | VW_NSO_1 | 10734 |   125K|   104   (2)| 00:00:02 |
|   7 |     HASH GROUP BY     |          | 10734 |   461K|   104   (2)| 00:00:02 |
|*  8 |      TABLE ACCESS FULL| CLM020A  | 10734 |   461K|   102   (0)| 00:00:02 |
|   9 |   VIEW                | VW_NSO_2 |    56 |  1792 |    23   (5)| 00:00:01 |
|* 10 |    FILTER             |          |       |       |            |          |
|  11 |     HASH GROUP BY     |          |     1 |   672 |    23   (5)| 00:00:01 |
|  12 |      TABLE ACCESS FULL| CLM010A  |  5532 | 66384 |    22   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

1 - access("CEDULA_REL"="CEDULA_REL")
2 - access("M".ROWID="FILA")
3 - access("CEDULA_REL"="CEDULA_REL")
4 - filter(LENGTH("NOMBRES_010")<=30 AND LENGTH("APELLIDOS_010")<=30)
5 - filter(LENGTH("CEDULA_REL")<=15)
8 - filter(("M"."TIPO_020"='E' OR "M"."TIPO_020"='S') AND
"M"."LUGARMOV_020" IS NOT NULL)
10 - filter(COUNT("CEDULA_REL")=1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM