Optimización de Queries en Salesforce (Parte 2) – con Query Plan y Tooling/REST API

Vimos en la entrada anterior que el objetivo de la optimización de consultas es conseguir:

  • Obtener el menor coste posible, es decir el mejor plan de ejecución
  • Que este coste sea inferior a 1, significando que la consulta es selectiva utilizando los índices creados

Como desarrolladores o administradores necesitamos validar si una consulta será selectiva antes de llegar a Producción, y mejorar su rendimiento.

Veremos en esta entrada las herramientas de las que disponemos para obtener los planes de ejecución y los costes asociados calculados por el Optimizer, y así anticipar problemas de rendimiento, y lo haremos no solo para consultas SOQL sinó también para Reports, List Views y Dashboards.

Lo haremos mediante la configuración y utilización de 2 herramientas:

  • Query Plan (muy conocida) de la que solo comentaré aspectos básicos y usos menos conocidos
  • El recurso explain de la REST API y de la Tooling API

Introducción

Son varios los motivos por los cuales podemos tener problemas de rendimiento en consultas a la BD:

  1. Desconocimiento de cómo conseguir Queries selectivas, funcionamiento del Optimizador y falta de experiencia (ver artículo anterior sobre optimización de queries).
  2. Que no se haya creado índices sobre los campos adecuados
  3. Que los volúmenes de los datos impidan al optimizador usar estos índices 
  4. (ver artículo anterior sobre optimización de queries).
  5. Que habiendo creado índices, estos presenten tamaños demasiado elevados como para que sean efectivos(ver artículo anterior sobre optimización de queries)
  6. Que habiendo creado índices sobre los campos adecuados, estemos utilizando operadores en nuestras cláusuas WHERE que no permiten ninguna optimización (ver artículo anterior sobre optimización de queries).
  7. Que las estadísticas de Salesforce no reflejen el volumen y densidad real de nuestros datos, porque hemos realizado operaciones DML (insert/delete/update) con grandes volúmenes y no se han actualizado aún las estadísticas.
  8. Que algunos mecanismos de optimización como índices, Skinny Tables, etc., se hayan deshabilitado por motivos desconocidos.

En cualquier de estos u otros casos, no tendremos ningún aviso de que una consulta está produciendo problemas de rendimiento, o que su coste ha empeorado y que en un futuro cercano producirá problemas de rendimiento, y por consiguiente problemas en Producción.

Para evaluar esta situación Salesforce nos proporciona 2 herramientas, que muchos administradores y desarrolladores utilizamos y que deben ser imprescindibles en tu día a día:

  1. Query Plan disponible en la Developer Console
  2. Recurso REST explain de la Tooling API ó REST API

Veamos cada una de las 2 y como utilizarlas en diversas situaciones.

Query Plan de la Developer Console

No me preguntes por qué, pero una de las herramientas más útiles de la Developer Console está desactivada por defecto, desde que apareció en Summer ’14, el Query Plan.

Para activarlo basta con acceder al menú de Help->Preferences, marcar la opción Enable Query Plan y aparecerá en la pestaña del Query Editor un  nuevo botón llamado Query Plan, como ves en la imagen.

Cómo activar el Query Plan en la Developer Console

Funcionalidades del Query Plan

El Query Plan permite, sin ejecutar realmente la consultaen nuestro entorno:

  1. Cost: Obtener el coste que ha calculado el Optimizer para una SOQL Query, Report ID, Dashboard ID, List View ID en el entorno en qué estamos.
  2. Leading Operation Type: el tipo de operación y el mecanismo de optimización que se utilizará, lo que llamaríamos en otros sistemas, la operación principal del plan de ejecución, y puede ser de 4 tipos:
    1. Index: se utilizará un índice.
    2. Other: se utilizaran mecanismos de optimización internos de Salesforce.
    3. Sharing: se utilizará un índice basado en las Sharing Rules que se han declarado en el Private Sharing Model del objeto, restringiendo así el número de registros afectados y ofreciendo un plan de ejecución más eficiente.
    4. TableScan: se realizará una lectura de todos los registros del objeto sobre el que se realiza la consulta.
  3. Fields:los campos sobre los que se va a producir una operación de optimización.
  4. Cardinality: El número de registros, que se devolverán cuando la Query, Report, Dashboard, List View se ejecute.
  5. Notes: los comentarios que nos ofrece el Optimizer a modo de indicaciones de los costes ofrecidos.
  6. sObject Cardinality: El número de registros que tiene el objeto sobre el cual se ejecuta la operación.
  7. sObject Type: el objeto sobre el cual realizamos la operación.

Para no estar repitiendo continuamente el cuarteto SOQL Query/Report/Dashboard/List View, a partir de ahora, utilizo Consulta, como su equivalente.

¿No sabes ordenar las columnas o qué? El motivo que aparezcan desordenados, es porque he listado los resultados en el orden de relevancia que en mi opinión proporciona el Optimizer.

Cómo utilizar Query Plan como un PRO

En este apartado veremos como usar el Query Plan para evaluar:

  • Una Query
  • Un Report mediante su ID
  • Una List View mediante su ID
  • Un Dashboard (obteniendo los IDs de sus Reports asociados )

Query Plan para una SOQL Query

Para una SOQL Query basta con copiar el código y ejecutar el Query Plan:

Plan de Ejecución de una Query que nos devuelve el Optimizer

Query Plan para un Report

Menos conocido es la utilización de Query Plan para evaluar el rendimiento de un Report.

Como vemos en la siguiente captura, tengo que incorporar índices y mejorar mi diseño de Query, porque todos los planes de ejecución del Optimizer producen costes muy elevados.

Si ya son elevados en mi Sandbox de desarollo, cuando promocionemos a Producción muy probablemente esta Query será un desastre.

Cómo obtener el Query Plan de un Report

Query Plan para una List View

Para una List View, es análogo a un Report, así de sencillo.

Cómo obtener el Query Plan de una List View

Query Plan para un Dashboard

Para un Dashboard necesitamos un paso previo y algo más de trabajo.

Dado que cada componente del Dashboard tiene un report asociado, primero debemos obtener estos Reports. Veamos un ejemplo partiendo del Dashboard de Salesforce para uso de licencias disponible en el Marketplace.

Está formado por 17 componentes que muestran información de las licencias. En la previsualización del Dashboard, seleccionamos su ID:

Un Dashboard está formado por varios Dashboard Components – en que cada uno de ellos está ligado a un Report

Ahora en tu IDE, en la misma Developer Console o en el Workbench ejecuta la siguiente consulta, obteniendo todos los IDs de los Reports utilizados en el Dashboard:

SELECT DashboardId, CustomReportId FROM DashboardComponent WHERE DashboardId = ‘….’

Con esta sencilla Query obtenemosla lista de Reports asociados al Dashboard

Ahora ya solo te queda volver a utilizar el Query Plan con estos identificadores, pan comido, ¿verdad?  Pero también algo tedioso, ¿no? Veamos como la Tooling API nos puede ayudar en esto.

Tooling API y Rest API

Con esta API obtenemos la información de los planes de ejecución de la misma forma que los obtenemos con Query Plan, pero mediante una invocación a un endpoint REST, lo que nos abre un mundo de posibilidades de automatización.

Es decir, la utilización de una API, nos permite la automatización de obtención de los planes de ejecución, que nos proporciona una potencia y eficiencia muy elevadas.

Veamos a continuación su funcionamiento dado que es muy simple:  invocamos el recurso https://instancia/services/data/v43.0/tooling/query/?explain=SOQL_ó_ID usando como parámetro el código SOQL en caso de una consulta ó el ID en caso de un Report ó una List View.

Veamos ejemplos de cada uno de ellos:

  • Para una consulta SOQL:
  • Para un Report:
  • Para una List View:
  • Para un Dashboard: aquí es algo distinto ya que debemos iterar por los todas las Queries utilizadas en el Dashboard e invocar la API para obtener su plan de ejecución:
Código para obtener todos los planes de ejecución de todas las Queries utilizadas en un Dashboard

El código completo está disponible en este repositorio: https://bitbucket.org/estevegraells/get-query-plans-for-a-salesforce-dashboard

Si te fijas bien, en los 3 primeros ejemplos no he usado el recurso de la Tooling API sinó de la REST API, y en el último caso he utilizado la Tooling.

En la siguiente entrada veremos un ejemplo completo, de momento, solo es necesario entender que ambas APIs tienen el recurso explain disponible.

Consideraciones y errores habituales

Es muy importante que tengas en cuenta los siguientes puntos:

  1. En los entornos previos iba bien“: el developer está formado, realizó las optimizaciones oportunas, pero no probó en un entorno con datos y volumetrías reales. Es decir, no pudo valorar si los índices eran los adecuados, sin sus densidades eran las esperadas y si la volumetría superaba los threadsholds. Por tanto, antes de llegar a Producción, habitualmente en nuestro Full Sandbox, con refresco reciente, es el lugar idóneo para realizar la comprobación de los planes de ejecución.
  2. El Optimizador utiliza las estadísticas para calcular los planes de ejecución. Obtener las estadísticas es un cálculo costoso, cuya actualización es diaria no espontánea (sino pides una actualización ad-hoc a soporte) con lo que puede suceder y sucede, que los resultados ofrecidos no coincidan exactamente con los datos de volumetría de registros que tienes actualmente en el entorno. Si la diferencia entre el real y el devuelto por el Optimizador es sustancial, el coste calculado será erróneo y por tanto el plan de ejecución inadecuado.
  3. El Optimizador no te indicará que campos deben ser indexados para obtener un mayor rendimiento, aunque a veces los comentarios devueltos puedan ser indicativos. Que no aparezcan recomendaciones de optimización significativas en el campo Notes, no implica de ninguna manera, que la consulta tenga un buen plan de ejecución, sino que, el Optimizador no escupe comentarios, nada más.
  4. “No habrá problema tiene un coste 0.9999”:  un coste cercano a 1, supone que en breve, este plan de ejecución dejará a la Query sin Selectividad, y muy probablemente producirá un problema de rendimiento, SIENDO ESTE el error de la mayoría de developers que están apremiados por entregar.
  5. Una Leading Operation de tipo TableScan aunque habitualmente es la operación con peor coste, no es siempre una mala operación ni implica mal rendimiento. Por ejemplo, en tablas con pocos registros, puede ser más eficiente recorrer la tabla entera, que acceder al índice para buscar los registros concretos. Esto no debe ser una excusa para no intentar siempre optimizar cualquier tabla de un volumen considerable, cuya operación seleccionada sea TableScan.

Mi recomendación es que:

  • Analices tus Queries, Reports y List View y obtengas el mejor plan de ejecución posible, con el menor coste posible. No te ciñas a la situación que tengas únicamente en este momento, sinó que es razonable que pase en un futuro a medio plazo.
  • Trabaja con volumetrías e índices reales con densidades reales.
  • No dejes la etapa de optimización para el final del Sprint o Proyecto, la creación de índices con el Soporte de Salesforce, así como otros recursos como Skinny Tables, detección de Skew Data lleva su tiempo, y debes darte tiempo para evaluarlo.

Próximos Pasos: y llegados a Producción ¿qué pasará a partir de ahora? ó ¿qué me encuentro si acabo de llegar?

En la siguiente entrada te mostraré una herramienta que te servirá para detectar la degradación de todas las consultas de tu ORG en PRO, ¿no sería útil que recibiéramos alarmas que algunas consultas se están degradando para diagnosticar las causas y solventarlo antes de que suponga un problema de rendimiento en producción?

Creo que puede ser de ayuda.

Enlaces interesantes

3 comentarios sobre “Optimización de Queries en Salesforce (Parte 2) – con Query Plan y Tooling/REST API

  1. tu herramienta se podría lanzar dentro de un sistema de integración continúa como parte de una pruebas mínimas para garantizar buen rendimiento antes de su paso a producción .

    algo asi como las métricas de código en entornos desarrollo a medida.

    Me gusta

    1. Aunque es buena idea, es poco viable, me explico: hay varios parámetros que afectan de forma determinante al plan de ejecución que solo están disponibles en tiempo de ejecución. Por ejemplo la mayoría de queries tienen parámetros dinámicos en las cláusulas WHERE o estan afectadas por las restricciones de visibilidad del usuario que la ejecuta. Mi intención, es que la herramienta, se ejecute en background, con las estadísticas reales, con valores de ejecución de queries ejecutadas y detectar la degradación del plan de ejecución. Espero poder liberarla pronto y entonces veremos si es útil. Un abrazo!!

      Me gusta

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.