DBQLObjTbl: ¿Acceso a vistas sin acceso a tablas?

(Based on a true story)

El cliente para el que estamos trabajando viene y nos pide que verifiquemos si se está accediendo a dos tablas que quiere eliminar (las llamaremos DBTablas.Tabla1 y DBTablas.Tabla2).

Chupado: vamos a DBQLObjTbl y vemos que, aunque hay algunos INSERTs y DELETEs (los de los procesos de carga), nadie ha hecho ningún SELECT sobre ellas desde hace semanas. Así se lo decimos.

Pero al rato vuelve y nos dice “pues hay algo que no me cuadra, porque a mí sí me salen SELECTs”.

Tras un par de miradas incrédulas, le decimos “muéstranoslo”.

Entonces va él y hace una “query” a DBQLSQLTbl con un “LIKE” con el nombre de la tabla en cuestión y obtiene múltiples resultados recientes de “queries” de tipo:

SELECT * FROM DBVistas."Tabla1"

Es decir, “queries” a una capa de acceso de vistas construídas sobre las tablas que estamos mirando.

Nuestra primera respuesta es: “OK. Eso es porque esas “queries” se han hecho con un usuario que no tiene activada la opcion OBJECTS en su QUERY LOGGING, por eso no las vimos cuando investigamos”.

Pero miramos el DBQLObjTbl para una de estas “queries” (por su QueryId) y vemos que la opción de QUERY LOGGING sí está activa para el usuario, pero que sólo hay registrados accesos a la base de datos de las vistas y a la vista:

QueryID ObjectDatabaseName ObjectTableName ObjectType
------- ------------------ --------------- ----------
nn...nn DBVistas           (null)          DB
nn...nn DBVistas           Tabla1          Viw

WTF???

¿Cómo es posible? ¿Cómo va a haber accesos a una vista sin accesos a su tabla subyacente? ¡Eso es imposible!

Miramos entonces DBQLStepTbl y vemos que no hay “steps” reales, sólo aparece el “step” virtual “RESP”.

Vamos a DBQLExplainTbl y vemos que el “query plan” existe y es correcto:

Explain:
  1) First, we lock DBTablas.Tabla1 in view DBVistas.Tabla1 for access
     With NoWait option. 
  2) Next, we do an all-AMPs RETRIEVE step from DBTablas.Tabla1 in view
     DBVistas.Tabla1 by way of an all-rows scan with no residual
     conditions into Spool 1 (group_amps), which is built locally on
     the AMPs. The size of Spool 1 is estimated with high confidence
     to be 666,458,833 rows (316,567,945,675 bytes). The estimated
     time for this step is 18.06 seconds. 
  -> The contents of Spool 1 are sent back to the user as the result of
     statement 1. The total estimated time is 18.06 seconds.

Más WTF!!!

Así que volvemos a mirar DBQLogTbl.

Y ahora nos damos cuenta de varias cosas:

No hay I/O, no hay AMPCPUTime, el NumSteps=0, y sólo hay un pequeño intervalo de “Parsing” (ParserCPUTime=0,02).

Pero lo más importante viene luego:

TxnMode=ANSI y RequestMode=Prep. Además, AppId=SAS.

Aquí es donde empezamos a ver la luz: resulta que esas “queries” ‘SELECT * FROM DBVistas.”Tabla1″‘ no están siendo ejecutadas, sino que sólo se realiza el “Parsing” (RequestMode=Prep), ya que SAS las envía como “PreparedStatement”. Seguramente se hace como algún mecanismo de comprobación rápida de existencia de objetos en la base de datos. Esto hace que sólo se verifiquen los objetos necesarios para la resolución de la “query”: la base de datos de vistas y la vista, que son los que efectivamente aparecen en DBQLObjTbl.

Para corroborar el argumento, ejecutamos la misma “query” y observamos como esta vez en DBQLObjTbl aparecen, además de los accesos a la base de datos de las vistas y la vista, accesos a la base de datos de las tablas, la tabla y sus columnas (es decir: lo normal y esperado).

Así que si eres, como yo, un buceador del “DBQL”, ten en cuenta que los “PreparedStatements” sólo accederán a los objetos primarios de la “query” para satisfacer la resolución de la misma, pero no a los objetos subyacentes. Al menos hasta que ésta no se ejecute realmente (con un executeQuery(), por ejemplo).

Saludos.

Carlos.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s

A %d blogueros les gusta esto: