sql >> Base de Datos >  >> RDS >> Oracle

Cambios de velocidad extraños con consulta sql

Para entender mejor lo que está pasando, prueba esto:

explain plan set statement_id = 'query1' for
SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5
     AND ck.prgrm_id = 1;

y luego:

select *
from table(dbms_xplan.display(statement_id=>'query1'));

Supongo que verá una línea que indica TABLE ACCESS FULL en Claim_key.

Entonces prueba:

explain plan set statement_id = 'query2' for
SELECT  count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5;

select *
from table(dbms_xplan.display(statement_id=>'query2'));

y verifique qué índice usa (presumiblemente). Eso debería darle una idea de lo que está haciendo la base de datos, lo que ayuda a descubrir por qué lo está haciendo

Bien, dados tus planes de explicación, es un ejemplo clásico de "los índices no siempre son buenos, las exploraciones de tablas no siempre son malas".

El ÍNDICE SKIP SCAN es donde la base de datos puede intentar usar un índice aunque la columna inicial del índice ni siquiera se use. Básicamente, si su índice se viera así (demasiado simplificado):

COL1   COL2   ROWID
A      X      1        <--
A      Y      2
A      Z      3
B      X      4        <--
B      Y      5
B      Z      6 

y su condición era DONDE col2 ='X', el escaneo de salto de índice dice que busque en cada combinación en COL1 donde col2 ='X'. "Omite" los valores en col1 una vez que encuentra una coincidencia (por ejemplo, col1 =A, col2 =X) hasta donde cambia el valor (col1 =B, luego col1 =C, etc.) y busca más coincidencias.

El problema es que los índices (¡generalmente!) funcionan así:1) encuentre el siguiente ID de fila en el índice donde se encontró el valor 2) vaya al bloque de la tabla con ese identificador de fila (ACCESO A LA MESA POR ÍNDICE ROWID) 3) repita hasta que no haya más coincidencias se encuentran.

(Para el escaneo de omisión, también incurriría en el costo de averiguar dónde está el próximo cambio de valor para las columnas principales).

Todo esto está muy bien para un pequeño número de filas, pero adolece de la ley de rendimientos decrecientes; no es tan bueno cuando tienes una gran cantidad de filas. Eso es porque tiene que leer un bloque de índice, luego un bloque de tabla, luego un bloque de índice, un bloque de tabla (incluso si el bloque de tabla se leyó previamente).

El escaneo completo de la tabla simplemente "explora" los datos gracias en parte a... lecturas multibloque. La base de datos puede leer muchos bloques del disco en una sola lectura y no lee el mismo bloque más de una vez.

El ÍNDICE FAST FULL SCAN básicamente trata el I_CLAIM_KEY_002 como una tabla. Todo lo que necesita en la consulta puede ser respondido solo por el índice; no se requiere ACCESO A LA MESA. (Supongo que I_CLAIM_KEY_002 se define como clnt_id, dte_of_srvce y clnt_id o dte_of_srvce no admite valores NULL. Dado que ck.id no debe ser un atributo nulo, un recuento en ck.id es lo mismo que un recuento en ck.clnt_id).

Entonces, en cuanto a su consulta inicial, a menos que desee modificar sus índices, intente esto:

SELECT  /*+ FULL(ck) */ count(ck.id)
FROM    claim_key ck
WHERE   (ck.dte_of_srvce > (SYSDATE - INTERVAL '30' DAY))
     AND ck.clm_type = 5
     AND ck.prgrm_id = 1

lo que forzará un escaneo completo de la tabla en Claim_key (ck) y podría ver un rendimiento similar al de los otros dos. (Verifique que este sea el caso primero anteponiendo la consulta con "explain plan set statement_id ='query_hint' for" y ejecutando la consulta dbms_xplan antes de ejecutarla).

(Ahora preguntará "¿Quiero poner pistas como esa todo el tiempo?" Por favor, no lo haga. Esto es solo para una prueba. Esto es solo para verificar si un FTS es mejor que el ÍNDICE SKIP SCAN Si es así, entonces necesitas averiguar por qué. :)

De todos modos... espero que haya tenido sentido... quiero decir sentido.