Plan de consulta y cronograma

Incorporado dentro de los trabajos de consulta, BigQuery incluye el plan de consultas de diagnóstico y la información del tiempo. Esto es similar a la información que proporcionan declaraciones como EXPLAIN en otras bases de datos y sistemas analíticos. Esta información se puede recuperar a partir de las respuestas de la API de métodos como jobs.get.

BigQuery actualizará de forma periódica estas estadísticas para las consultas de larga duración. Estas actualizaciones ocurren sin importar la velocidad a la que se consulta el estado del trabajo, pero, por lo general, su frecuencia máxima será cada 30 segundos. Además, los trabajos de consulta que no usan recursos de ejecución, como las solicitudes de prueba o los resultados que pueden entregarse a partir de los resultados almacenados en caché, no incluirán la información de diagnóstico adicional, aunque es posible que existan otras estadísticas.

Fondo

Cuando BigQuery ejecuta una consulta, convierte el código SQL en un grafo de ejecución que consta de etapas. Las etapas se componen de pasos, que son las operaciones elementales que realizan la lógica de la búsqueda. BigQuery aprovecha una arquitectura en paralelo muy distribuida que ejecuta etapas en paralelo para reducir la latencia. Las etapas se comunican entre sí a través de Shuffle, una arquitectura de memoria distribuida rápida.

El plan de consulta usa los términos unidades de trabajo y trabajadores para describir el paralelismo de la etapa. En otras partes de BigQuery, puede aparecer el término ranura, que es una representación abstracta de varias facetas de la ejecución de consultas, incluidos los recursos de procesamiento, de memoria y de E/S. Las ranuras ejecutan las unidades de trabajo individuales de una etapa en paralelo. Las estadísticas de trabajo principales proporcionan el costo de consulta individual con totalSlotMs según esta contabilidad abstracta.

Otra propiedad importante de la ejecución de consultas es que BigQuery puede modificar el plan de consultas mientras se ejecuta una consulta. Por ejemplo, BigQuery introduce etapas de repartición para mejorar la distribución de datos entre los trabajadores de consultas, lo que mejora el paralelismo y reduce la latencia de las consultas.

Además del plan de consulta, los trabajos de consulta también exponen un cronograma de ejecución que proporciona un conteo de unidades de trabajo completadas, pendientes y activas. Una consulta puede tener varias etapas con trabajadores activos en simultáneo, y el cronograma está previsto para mostrar el progreso general de la consulta.

Visualiza el gráfico de ejecución con la consola de Google Cloud

En la consola deGoogle Cloud , puedes ver los detalles del plan de consultas de una que se haya completado. Para ello, haz clic en el botón Detalles de la ejecución.

Es el plan de consultas.

Información del plan de consultas

Dentro de la respuesta de la API, los planes de consultas se representan como una lista de etapas de consulta. Cada elemento de la lista muestra estadísticas de descripción general por etapa, información detallada de los pasos y clasificaciones del tiempo de las etapas. No todos los detalles se renderizan en la consola de Google Cloud , pero todos pueden estar presentes en las respuestas de la API.

Comprende el gráfico de ejecución

En la Google Cloud consola, puedes ver los detalles del plan de consulta haciendo clic en la pestañaGráfico de ejecución.

La pestaña del gráfico de ejecución

El panel Gráfico de ejecución se organiza de la siguiente manera:

Diseño del gráfico de ejecución.

  • En el centro, se encuentra el gráfico de ejecución. Muestra las etapas como nodos y la memoria aleatoria intercambiada entre las etapas como bordes.
  • El panel izquierdo tiene el mapa de calor del texto de la búsqueda. Muestra el texto de la consulta principal que se ejecutó junto con las vistas a las que se hace referencia.
  • El panel derecho contiene los detalles de la consulta o la etapa.

El gráfico de ejecución aplica un esquema de color a los nodos del gráfico según el tiempo de ranura, en el que los nodos con un rojo más oscuro tardan más tiempo de ranura en relación con el resto de las etapas del gráfico.

Para navegar por el gráfico de ejecución, puedes hacer lo siguiente:

  • Mantén presionado el fondo del gráfico para desplazarte a diferentes áreas.
  • Usa la rueda del mouse para acercar y alejar el gráfico.
  • Mantén presionado el minimapa en la parte superior derecha para desplazarte a diferentes áreas del gráfico.

Si haces clic en una etapa del gráfico, se muestran los detalles de la etapa seleccionada. Los detalles de la etapa incluyen lo siguiente:

  • Estadísticas. Consulta Descripción general de la etapa para obtener detalles sobre las estadísticas.
  • Son los detalles del paso. Los pasos describen las operaciones individuales que ejecutan la lógica de la consulta.

Detalles del paso

Las etapas se componen de pasos, que son las operaciones individuales que ejecutan la lógica de la consulta. Los pasos tienen subpasos que describen lo que hizo el paso en pseudocódigo. Los subpasos usan variables para describir las relaciones entre los pasos. Las variables comienzan con un signo de dólar seguido de un número único. Los números de variables no se comparten entre las etapas.

En la siguiente imagen, se muestran los pasos de las etapas:

Son los detalles del paso del gráfico de ejecución.

A continuación, se muestra un ejemplo de los pasos de una etapa:

  READ
  $30:l_orderkey, $31:l_quantity
  FROM lineitem

  AGGREGATE
  GROUP BY $100 := $30
  $70 := SUM($31)

  WRITE
  $100, $70
  TO __stage00_output
  BY HASH($100)

En los pasos del ejemplo, se describe lo siguiente:

  • La etapa leyó las columnas l_orderkey y l_quantity de la tabla lineitem y almacenó los valores en las variables $30 y $31, respectivamente.
  • La etapa agregó las variables $30 y $31, y almacenó las agregaciones en las variables $100 y $70, respectivamente.
  • La etapa escribió los resultados de las variables $100 y $70 para mezclarlos. La etapa ordenó los resultados en la memoria de shuffle según USD 100.

Consulta Cómo interpretar y optimizar los pasos para obtener todos los detalles sobre los tipos de pasos y cómo optimizarlos.

BigQuery podría truncar los pasos secundarios cuando el gráfico de ejecución de la consulta era lo suficientemente complejo como para que proporcionar pasos secundarios completos causara problemas de tamaño de carga útil al recuperar la información de la consulta.

Mapa de calor del texto de la búsqueda

Para solicitar comentarios o asistencia para esta función, envía un correo electrónico a bq-performance-troubleshooting+feedback@google.com.

BigQuery puede asignar algunos pasos de la etapa a partes del texto de la consulta. El mapa de calor del texto de la búsqueda muestra todo el texto de la búsqueda correspondiente con los pasos de la etapa. Destaca el texto de la búsqueda según el tiempo total de ranura de las etapas cuyos pasos tienen texto de búsqueda asignado.

En la siguiente imagen, se muestra el texto de la búsqueda destacado:

Texto de la consulta destacado en el gráfico de ejecución.

Si mantienes el puntero sobre una parte asignada del texto de la búsqueda, se muestra una sugerencia que enumera todos los pasos de la etapa que se asignan al texto de la búsqueda junto con el tiempo de la ranura de la etapa. Si haces clic en un texto de búsqueda asignado, se selecciona la etapa en el gráfico de ejecución y se abren los detalles de la etapa en el panel derecho.

El gráfico de ejecución asocia el texto de la consulta con la etapa.

Una sola parte del texto de la búsqueda se puede asignar a varias etapas. La información sobre la herramienta enumera cada etapa asignada y su hora de intervalo. Si haces clic en el texto de la consulta, se destacan las etapas correspondientes y se atenúa el resto del gráfico. Si haces clic en una etapa específica, se mostrarán sus detalles.

En la siguiente imagen, se muestra cómo se relaciona el texto de la búsqueda con los detalles del paso:

El gráfico de ejecución asocia el texto de la búsqueda con el paso.

En la sección Detalles del paso de una etapa, si un paso se asigna a texto de búsqueda, el paso tiene un ícono de código. Si haces clic en el ícono de código, se destacará la parte asignada del texto de la búsqueda a la izquierda.

Es importante tener en cuenta que el color del mapa de calor se basa en el tiempo de intervalo de toda la etapa. Como BigQuery no mide el tiempo de ranura de los pasos, el mapa de calor no representa el tiempo de ranura real de esa parte específica del texto de la consulta asignado. En la mayoría de los casos, una etapa realiza un solo paso complejo, como una unión o una agregación. Por lo tanto, el color del mapa de calor es adecuado. Sin embargo, cuando una etapa se compone de pasos que realizan varias operaciones complejas, el color del mapa de calor puede representar en exceso el tiempo de intervalo real en el mapa de calor. En estos casos, es importante comprender los otros pasos que componen la etapa para obtener una comprensión más completa del rendimiento de la búsqueda.

Descripción general de la etapa

Los campos de descripción general de cada etapa pueden incluir lo siguiente:

Campo de API Descripción
id ID numérico exclusivo para la etapa.
name Nombre de resumen sencillo de la etapa. Los steps dentro de la etapa proporcionan detalles adicionales sobre los pasos de ejecución.
status Estado de ejecución de la etapa. Entre los estados posibles, se incluyen PENDIENTE, EN EJECUCIÓN, COMPLETO, CON ERRORES Y CANCELADO.
inputStages Una lista de los ID que forman el grafo de dependencia de la etapa. Por ejemplo, en una etapa JOIN, se suelen necesitar dos etapas dependientes que preparan los datos en el lado izquierdo y derecho de la relación JOIN.
startMs Marca de tiempo en milisegundos de ciclo de entrenamiento, que representa el momento cuando el primer trabajador dentro de la etapa comenzó la ejecución.
endMs Marca de tiempo en milisegundos de ciclo de entrenamiento, que representa el momento cuando el último trabajador completó la ejecución.
steps Lista más detallada de pasos de ejecución dentro de la etapa. Consulta la siguiente sección para obtener más información.
recordsRead Tamaño de entrada de la etapa como número de registros en todos los trabajadores de la etapa.
recordsWritten Tamaño de salida de la etapa como número de registros en todos los trabajadores de la etapa.
parallelInputs Número de unidades de trabajo que se pueden paralelizar para la etapa. Según la etapa y la consulta, esto puede representar la cantidad de segmentos de columnas de una tabla o la cantidad de particiones de un orden aleatorio intermedio.
completedParallelInputs Número de unidades de trabajo en la etapa que se completaron. Para algunas consultas, no todas las entradas en una etapa deben completarse a fin de que la etapa se complete.
shuffleOutputBytes Representa el total de bytes escritos en todos los trabajadores dentro de una etapa de consulta.
shuffleOutputBytesSpilled Es posible que las consultas que transmiten datos importantes entre etapas deban recurrir a la transmisión basada en disco. La estadística de bytes volcados comunica la cantidad de datos volcados al disco. Depende de un algoritmo de optimización, por lo que no es determinista para ninguna consulta determinada.

Clasificación de tiempo por etapa

Las etapas de consulta proporcionan clasificaciones de tiempo por etapa en forma relativa y absoluta. Como cada etapa de ejecución representa el trabajo que realizaron los trabajadores independientes, la información se proporciona en el tiempo promedio y en el peor de los casos. Estos tiempos representan el rendimiento promedio de todos los trabajadores de una etapa, así como el rendimiento del trabajador de cola larga más lento de una clasificación determinada. Además, los tiempos promedio y máximo se desglosan en representaciones absolutas y relativas. Para las estadísticas basadas en la proporción, los datos se proporcionan como una fracción del tiempo más prolongado que cualquier trabajador invirtió en cualquier segmento.

La Google Cloud consola presenta el tiempo por etapas con las representaciones de tiempo relativas.

La información del tiempo por etapas se muestra de la siguiente manera:

Tiempo relativo Tiempo absoluto Numerador de proporción
waitRatioAvg waitMsAvg Tiempo que el trabajador promedio esperó para programarse.
waitRatioMax waitMsMax Tiempo que el trabajador más lento esperó para programarse.
readRatioAvg readMsAvg Tiempo que el trabajador promedio dedicó a leer datos de entrada.
readRatioMax readMsMax Tiempo que el trabajador más lento dedicó a leer datos de entrada.
computeRatioAvg computeMsAvg Tiempo que el trabajador promedio pasó vinculado a la CPU.
computeRatioMax computeMsMax Tiempo que el trabajador más lento pasó vinculado a la CPU.
writeRatioAvg writeMsAvg Tiempo que el trabajador promedio dedicó a escribir datos de salida.
writeRatioMax writeMsMax Tiempo que el trabajador más lento dedicó a escribir datos de salida.

Descripción general del paso

Los pasos contienen las operaciones que cada trabajador dentro de una etapa ejecuta, presentadas como una lista ordenada de operaciones. Cada operación de paso tiene una categoría, y algunas operaciones proporcionan información más detallada. Las categorías de operación que se encuentran en el plan de consultas incluyen lo siguiente:

Categoría del paso Descripción
READ Lectura de una o más columnas desde una tabla de entrada o desde Shuffle intermedio. Solo se muestran las primeras dieciséis columnas que se leen en los detalles del paso.
WRITE Escritura de una o más columnas en una tabla de salida o en Shuffle intermedio. Para las salidas con particiones HASH de una etapa, esto también incluye las columnas que se usan como clave de partición.
COMPUTE Evaluación de expresiones y funciones de SQL.
FILTER Se usa en las cláusulas WHERE, OMIT IF y HAVING.
SORT Operación ORDER BY que incluye las claves de columna y el orden de clasificación.
AGGREGATE Implementa agregaciones para cláusulas como GROUP BY o COUNT, entre otras.
LIMIT Implementa la cláusula LIMIT.
JOIN Implementa uniones para cláusulas como JOIN, entre otras. Incluye el tipo de unión y, posiblemente, las condiciones de unión.
ANALYTIC_FUNCTION Invocación de una función analítica.
USER_DEFINED_FUNCTION Es una invocación a una función definida por el usuario.

Comprende los pasos con el texto de la búsqueda

Para obtener asistencia durante la vista previa, envía un correo electrónico a bq-query-inspector-feedback@google.com.

Comprender cómo se relacionan los pasos de la etapa con la búsqueda puede ser un desafío. En la sección Texto de la consulta, se muestra cómo algunos pasos se relacionan con el texto de la consulta original.

En la sección Texto de la búsqueda, se destacan diferentes partes del texto de la búsqueda original y se muestran los pasos que se correlacionan con el texto de la búsqueda inmediatamente anterior al texto de la búsqueda original destacado. Solo los pasos que se encuentran inmediatamente arriba de una parte destacada del texto de la búsqueda original se aplican al texto de la búsqueda destacado.

Es el gráfico de ejecución con el texto de la consulta de la etapa.

En el ejemplo de captura de pantalla, se muestran las siguientes asignaciones:

  • El paso AGGREGATE: GROUP BY $100 := $30 se asigna al texto de la búsqueda select l_orderkey.

  • El paso READ: FROM lineitem se asigna al texto de la búsqueda select ... from lineitem.

  • El paso AGGREGATE: $70 := SUM($31) se asigna al texto de la búsqueda sum(l_quantity).

No todos los pasos se pueden correlacionar con el texto de la búsqueda.

Si una consulta usa vistas y los pasos de la etapa tienen asignaciones al texto de la consulta de una vista, en la sección Texto de la consulta se muestran el nombre de la vista y el texto de la consulta de la vista con sus asignaciones. Sin embargo, si se borra la vista o si pierdes el bigquery.tables.get permiso de IAM para la vista, la sección Texto de la consulta no mostrará las asignaciones de los pasos de la etapa para la vista.

Pasos para interpretar y optimizar

En las siguientes secciones, se explica cómo interpretar los pasos de un plan de consultas y se proporcionan formas de optimizar tus consultas.

Paso READ

El paso READ significa que una etapa está accediendo a los datos para su procesamiento. Los datos se pueden leer directamente desde las tablas a las que se hace referencia en una consulta o desde la memoria de reorganización. Cuando se leen datos de una etapa anterior, BigQuery los lee de la memoria de intercambio. La cantidad de datos analizados afecta el costo cuando se usan ranuras a pedido y el rendimiento cuando se usan reservas.

Posibles problemas de rendimiento

  • Análisis grande de una tabla sin particionar: Si la consulta solo necesita una pequeña porción de los datos, esto podría indicar que un análisis de tabla es ineficiente. La partición podría ser una buena estrategia de optimización.
  • Análisis de una tabla grande con una proporción de filtro pequeña: Esto sugiere que el filtro no reduce de manera eficaz los datos analizados. Considera revisar las condiciones del filtro.
  • Bytes de Shuffle volcados en el disco: Esto sugiere que los datos no se almacenan de manera eficaz con técnicas de optimización, como el agrupamiento en clústeres, que podría mantener datos similares en clústeres.

Optimizar

  • Filtrado segmentado: Usa las cláusulas WHERE de forma estratégica para filtrar los datos irrelevantes lo antes posible en la consulta. Esto reduce la cantidad de datos que debe procesar la consulta.
  • Particionamiento y agrupamiento en clústeres: BigQuery usa el particionamiento y el agrupamiento en clústeres de tablas para ubicar de manera eficiente segmentos de datos específicos. Asegúrate de que tus tablas estén particionadas y agrupadas en clústeres según tus patrones de consultas típicos para minimizar los datos analizados durante los pasos de READ.
  • Selecciona columnas pertinentes: Evita usar instrucciones SELECT *. En su lugar, selecciona columnas específicas o usa SELECT * EXCEPT para evitar leer datos innecesarios.
  • Vistas materializadas: Las vistas materializadas pueden precalcular y almacenar agregaciones que se usan con frecuencia, lo que podría reducir la necesidad de leer tablas básicas durante los pasos de READ para las consultas que usan esas vistas.

Paso COMPUTE

En el paso COMPUTE, BigQuery realiza las siguientes acciones en tus datos:

  • Evalúa las expresiones en las cláusulas SELECT, WHERE, HAVING y otras de la consulta, incluidos los cálculos, las comparaciones y las operaciones lógicas.
  • Ejecuta funciones de SQL integradas y funciones definidas por el usuario.
  • Filtra las filas de datos según las condiciones de la consulta.

Optimizar

El plan de consulta puede revelar los cuellos de botella dentro del paso COMPUTE. Busca etapas con cálculos extensos o una gran cantidad de filas procesadas.

  • Correlaciona el paso COMPUTE con el volumen de datos: Si una etapa muestra un procesamiento significativo y procesa un gran volumen de datos, es posible que sea un buen candidato para la optimización.
  • Datos sesgados: En las etapas en las que el máximo de procesamiento es significativamente mayor que el promedio de procesamiento, esto indica que la etapa dedicó una cantidad desproporcionada de tiempo a procesar algunas segmentaciones de datos. Considera observar la distribución de los datos para ver si hay sesgo en ellos.
  • Considera los tipos de datos: Usa los tipos de datos adecuados para tus columnas. Por ejemplo, usar números enteros, fechas y horas, y marcas de tiempo en lugar de cadenas puede mejorar el rendimiento.

Paso WRITE

Los pasos de WRITE se aplican a los datos intermedios y al resultado final.

  • Escritura en la memoria de redistribución: En una consulta de varias etapas, el paso WRITE suele implicar el envío de los datos procesados a otra etapa para su posterior procesamiento. Esto es típico de la memoria de aleatorización, que combina o agrega datos de varias fuentes. Los datos que se escriben durante esta etapa suelen ser un resultado intermedio, no el resultado final.
  • Salida final: El resultado de la consulta se escribe en el destino o en una tabla temporal.

Partición de hash

Cuando una etapa del plan de consulta escribe datos en un resultado particionado por hash, BigQuery escribe las columnas incluidas en el resultado y la columna elegida como clave de partición.

Optimizar

Si bien el paso WRITE en sí no se puede optimizar directamente, comprender su función puede ayudarte a identificar posibles cuellos de botella en etapas anteriores:

  • Minimiza los datos escritos: Enfócate en optimizar las etapas anteriores con el filtrado y la agregación para reducir la cantidad de datos escritos durante este paso.
  • Particionamiento: La escritura se beneficia en gran medida del particionamiento de tablas. Si los datos que escribes se limitan a particiones específicas, BigQuery puede realizar escrituras más rápidas.

    Si la declaración DML tiene una cláusula WHERE con una condición estática en relación con una columna de partición de la tabla, BigQuery solo modifica las particiones de la tabla pertinentes.

  • Compensaciones de la desnormalización: A veces, la desnormalización puede generar conjuntos de resultados más pequeños en el paso intermedio WRITE. Sin embargo, existen desventajas, como el aumento del uso del almacenamiento y los desafíos relacionados con la coherencia de los datos.

Paso JOIN

En el paso JOIN, BigQuery combina datos de dos fuentes de datos. Las uniones pueden incluir condiciones de unión. Las uniones requieren muchos recursos. Cuando se unen datos grandes en BigQuery, las claves de unión se redistribuyen de forma independiente para alinearse en la misma ranura, de modo que la unión se realice de forma local en cada ranura.

Por lo general, el plan de consulta para el paso JOIN revela los siguientes detalles:

  • Patrón de unión: Indica el tipo de unión que se usó. Cada tipo define cuántas filas de las tablas combinadas se incluyen en el conjunto de resultados.
  • Columnas de unión: Son las columnas que se usan para hacer coincidir las filas entre las fuentes de datos. La elección de las columnas es fundamental para el rendimiento de la unión.

Patrones de unión

  • Unión por transmisión: Cuando una tabla, por lo general la más pequeña, puede caber en la memoria de un solo nodo o ranura de trabajador, BigQuery puede transmitirla a todos los demás nodos para realizar la unión de manera eficiente. Busca JOIN EACH WITH ALL en los detalles del paso.
  • Unión hash: Cuando las tablas son grandes o una unión de transmisión no es adecuada, se puede usar una unión hash. BigQuery usa operaciones de hash y shuffle para mezclar las tablas izquierda y derecha, de modo que las claves coincidentes terminen en la misma ranura para realizar una unión local. Las uniones hash son una operación costosa, ya que los datos deben transferirse, pero permiten una correlación eficiente de las filas entre los hashes. Busca JOIN EACH WITH EACH en los detalles del paso.
  • Unión de tabla con sí misma: Es un antipatrón de SQL en el que una tabla se une consigo misma.
  • Unión cruzada: Es un antipatrón de SQL que puede causar problemas de rendimiento significativos porque genera datos de salida más grandes que las entradas.
  • Unión sesgada: La distribución de datos en la clave de unión de una tabla está muy sesgada y puede generar problemas de rendimiento. Busca casos en los que el tiempo máximo de procesamiento sea mucho mayor que el tiempo promedio de procesamiento en el plan de consultas. Para obtener más información, consulta Combinación de alta cardinalidad y Sesgo de partición.

Depuración

  • Gran volumen de datos: Si el plan de consulta muestra una cantidad significativa de datos procesados durante el paso JOIN, investiga la condición de unión y las claves de unión. Considera filtrar o usar claves de combinación más selectivas.
  • Distribución sesgada de los datos: Analiza la distribución de los datos de las claves de unión. Si una tabla está muy sesgada, explora estrategias como dividir la consulta o aplicar un filtro previo.
  • Uniones de alta cardinalidad: Las uniones que producen muchas más filas que la cantidad de filas de entrada a la izquierda y a la derecha pueden reducir drásticamente el rendimiento de las consultas. Evita las uniones que producen una gran cantidad de filas.
  • Orden incorrecto de la tabla: Asegúrate de haber elegido el tipo de unión adecuado, como INNER o LEFT, y de haber ordenado las tablas de mayor a menor según los requisitos de tu consulta.

Optimizar

  • Claves de combinación selectivas: Para las claves de combinación, usa INT64 en lugar de STRING cuando sea posible. Las comparaciones de STRING son más lentas que las de INT64 porque comparan cada carácter de una cadena. Los números enteros solo requieren una comparación.
  • Filtrar antes de la unión: Aplica filtros de cláusula WHERE en tablas individuales antes de la unión. Esto reduce la cantidad de datos involucrados en la operación de unión.
  • Evita las funciones en las columnas de unión: Evita llamar a funciones en las columnas de unión. En cambio, estandariza los datos de la tabla durante el proceso de transferencia o posterior a la transferencia con canalizaciones de SQL de ELT. Este enfoque elimina la necesidad de modificar las columnas de unión de forma dinámica, lo que permite uniones más eficientes sin comprometer la integridad de los datos.
  • Evita las uniones de tabla con sí misma: Las uniones de tabla con sí misma se usan comúnmente para calcular relaciones que dependen de las filas. Sin embargo, las uniones de tabla con sí misma pueden cuadruplicar la cantidad de filas de salida, lo que genera problemas de rendimiento. En lugar de depender de las uniones de tabla con sí misma, considera usar funciones analíticas.
  • Tablas grandes primero: Aunque el optimizador de consulta en SQL puede determinar qué tabla debe estar en qué lado de la unión, ordena las tablas unidas de forma adecuada. La práctica recomendada es colocar primero la tabla más grande, seguida de la más pequeña y, luego, en tamaño decreciente.
  • Desnormalización: En algunos casos, la desnormalización estratégica de las tablas (agregar datos redundantes) puede eliminar las uniones por completo. Sin embargo, este enfoque tiene desventajas en cuanto al almacenamiento y la coherencia de los datos.
  • Particionamiento y agrupamiento en clústeres: Particionar las tablas en función de las claves de unión y agrupar en clústeres los datos ubicados en el mismo lugar puede acelerar significativamente las uniones, ya que permite que BigQuery segmente las particiones de datos pertinentes.
  • Optimiza las uniones sesgadas: Para evitar problemas de rendimiento asociados con las uniones sesgadas, filtra previamente los datos de la tabla lo antes posible o divide la consulta en dos o más consultas.

Paso AGGREGATE

En el paso AGGREGATE, BigQuery agrega y agrupa los datos.

Depuración

  • Detalles de la etapa: Verifica la cantidad de filas de entrada y salida de la agregación, y el tamaño de la aleatorización para determinar cuánta reducción de datos se logró en el paso de agregación y si se realizó una aleatorización de datos.
  • Tamaño de Shuffle: Un tamaño de Shuffle grande puede indicar que se transfirió una cantidad significativa de datos entre los nodos trabajadores durante la agregación.
  • Verifica la distribución de datos: Asegúrate de que los datos estén distribuidos de manera uniforme entre las particiones. La distribución de datos sesgada puede generar cargas de trabajo desequilibradas en el paso de agregación.
  • Revisa las agregaciones: Analiza las cláusulas de agregación para confirmar que sean necesarias y eficientes.

Optimizar

  • Agrupamiento en clústeres: Agrupa tus tablas en clústeres según las columnas que se usan con frecuencia en GROUP BY, COUNT o en otras cláusulas de agregación.
  • Particionamiento: Elige una estrategia de particionamiento que se alinee con tus patrones de búsqueda. Considera usar tablas particionadas por tiempo de transferencia para reducir la cantidad de datos analizados durante la agregación.
  • Agrega antes: Si es posible, realiza las agregaciones antes en la canalización de consultas. Esto puede reducir la cantidad de datos que se deben procesar durante la agregación.
  • Optimización del orden aleatorio: Si el orden aleatorio es un cuello de botella, explora formas de minimizarlo. Por ejemplo, puedes desnormalizar tablas o usar la agrupación en clústeres para colocar datos relevantes.

Casos extremos

  • Agregaciones DISTINCT: Las consultas con agregaciones DISTINCT pueden ser costosas en términos de procesamiento, en especial en conjuntos de datos grandes. Considera alternativas como APPROX_COUNT_DISTINCT para obtener resultados aproximados.
  • Gran cantidad de grupos: Si la búsqueda produce una gran cantidad de grupos, es posible que consuma una cantidad considerable de memoria. En esos casos, considera limitar la cantidad de grupos o usar otra estrategia de agregación.

Paso REPARTITION

REPARTITION y COALESCE son técnicas de optimización que BigQuery aplica directamente a los datos aleatorizados en la consulta.

  • REPARTITION: Esta operación tiene como objetivo reequilibrar la distribución de datos en los nodos de trabajo. Supongamos que, después de la reorganización, un nodo trabajador termina con una cantidad de datos desproporcionadamente grande. El paso REPARTITION redistribuye los datos de manera más uniforme, lo que evita que un solo trabajador se convierta en un cuello de botella. Esto es especialmente importante para las operaciones que requieren una gran cantidad de recursos de procesamiento, como las uniones.
  • COALESCE: Este paso se produce cuando tienes muchos buckets pequeños de datos después de la aleatorización. El paso COALESCE combina estos buckets en otros más grandes, lo que reduce la sobrecarga asociada a la administración de numerosos fragmentos pequeños de datos. Esto puede ser especialmente beneficioso cuando se trabaja con conjuntos de resultados intermedios muy pequeños.

Si ves pasos REPARTITION o COALESCE en tu plan de consulta, no significa necesariamente que haya un problema con tu consulta. A menudo, es un signo de que BigQuery optimiza de forma proactiva la distribución de datos para mejorar el rendimiento. Sin embargo, si ves estas operaciones repetidamente, es posible que tus datos estén inherentemente sesgados o que tu consulta esté causando una reorganización excesiva de los datos.

Optimizar

Para reducir la cantidad de pasos de REPARTITION, prueba lo siguiente:

  • Distribución de datos: Asegúrate de que tus tablas estén particionadas y agrupadas de manera eficaz. Los datos bien distribuidos reducen la probabilidad de que se produzcan desequilibrios significativos después de la aleatorización.
  • Estructura de la consulta: Analiza la consulta para identificar posibles fuentes de sesgo en los datos. Por ejemplo, ¿hay filtros o uniones muy selectivos que hacen que se procese un pequeño subconjunto de datos en un solo trabajador?
  • Estrategias de unión: Experimenta con diferentes estrategias de unión para ver si generan una distribución de datos más equilibrada.

Para reducir la cantidad de pasos de COALESCE, prueba lo siguiente:

  • Estrategias de agregación: Considera realizar agregaciones antes en la canalización de consultas. Esto puede ayudar a reducir la cantidad de conjuntos de resultados intermedios pequeños que podrían causar pasos de COALESCE.
  • Volumen de datos: Si trabajas con conjuntos de datos muy pequeños, es posible que COALESCE no sea una preocupación importante.

No optimices en exceso. La optimización prematura puede hacer que tus consultas sean más complejas sin generar beneficios significativos.

Explicación de las consultas federadas

Las consultas federadas te permiten enviar una declaración de consulta a una fuente de datos externa a través de la función EXTERNAL_QUERY. Las consultas federadas están sujetas a la técnica de optimización conocida como envíos de SQL, y el plan de consultas muestra las operaciones enviadas a la fuente de datos externa, si la hubiera. Por ejemplo, si ejecutas la siguiente consulta:

SELECT id, name
FROM EXTERNAL_QUERY("<connection>", "SELECT * FROM company")
WHERE country_code IN ('ee', 'hu') AND name like '%TV%'

El plan de consulta mostrará los siguientes pasos de etapa:

$1:id, $2:name, $3:country_code
FROM table_for_external_query_$_0(
  SELECT id, name, country_code
  FROM (
    /*native_query*/
    SELECT * FROM company
  )
  WHERE in(country_code, 'ee', 'hu')
)
WHERE and(in($3, 'ee', 'hu'), like($2, '%TV%'))
$1, $2
TO __stage00_output

En este plan, table_for_external_query_$_0(...) representa la función EXTERNAL_QUERY. Entre paréntesis puedes ver la consulta que ejecuta la fuente de datos externa. En función de eso, puedes notar lo siguiente:

  • Una fuente de datos externa muestra solo 3 columnas seleccionadas.
  • Una fuente de datos externa solo muestra filas en las que country_code es 'ee' o 'hu'.
  • El operador LIKE no se envía hacia abajo y BigQuery lo evalúa.

A modo de comparación, si no hay pushdown, el plan de consulta mostrará los siguientes pasos de etapa:

$1:id, $2:name, $3:country_code
FROM table_for_external_query_$_0(
  SELECT id, name, description, country_code, primary_address, secondary address
  FROM (
    /*native_query*/
    SELECT * FROM company
  )
)
WHERE and(in($3, 'ee', 'hu'), like($2, '%TV%'))
$1, $2
TO __stage00_output

Esta vez, una fuente de datos externa muestra todas las columnas y todas las filas de la tabla company, y BigQuery realiza el filtrado.

Metadatos de cronograma

En los cronogramas de consultas, se informa el progreso en puntos específicos en el tiempo, lo que proporciona vistas instantáneas del progreso general de la consulta. El cronograma se representa como una serie de muestras en las que se informan los siguientes detalles:

Campo Descripción
elapsedMs Milisegundos transcurridos desde el inicio de la ejecución de la consulta.
totalSlotMs Una representación acumulativa de los milisegundos de ranura que usó la consulta.
pendingUnits Total de unidades de trabajo programadas y en espera de ejecución.
activeUnits Total de unidades de trabajo activas que los trabajadores procesan.
completedUnits Total de unidades de trabajo que se completaron mientras se ejecutaba esta consulta.

Consulta de ejemplo

En la siguiente consulta, se cuentan la cantidad de filas en el conjunto de datos públicos de Shakespeare. Esta tiene un segundo recuento condicional que restringe los resultados a las filas que hacen referencia a “hamlet”:

SELECT
  COUNT(1) as rowcount,
  COUNTIF(corpus = 'hamlet') as rowcount_hamlet
FROM `publicdata.samples.shakespeare`

Haz clic en Detalles de la ejecución para ver el plan de consulta:

El plan de consultas de Hamlet.

Los indicadores de color muestran los tiempos relativos de todos los pasos en todas las etapas.

Para obtener más información sobre los pasos de las etapas de ejecución, haz clic en a fin de expandir los detalles de la etapa:

Detalles del paso del plan de consulta de Hamlet.

En este ejemplo, el tiempo más prolongado en cualquier segmento fue el tiempo que el trabajador único en la etapa 01 esperó a que se completara la etapa 00. Esto se debe a que la etapa 01 dependía de la entrada de la etapa 00 y no podía comenzar hasta que la primera etapa escribió su salida en un orden aleatorio intermedio.

Informes de errores

Es posible que los trabajos de consulta fallen a mitad de la ejecución. Debido a que la información del plan se actualiza de forma periódica, podrás observar dónde se produjo la falla en el grafo de ejecución. Dentro de la consola de Google Cloud , las etapas correctas o con fallas se etiquetan con una marca de verificación o un signo de exclamación junto al nombre de la etapa.

Para obtener más información sobre cómo interpretar y abordar errores, consulta la Guía de solución de problemas.

Representación de muestra de la API

La información del plan de consulta está incorporada en la información de la respuesta del trabajo y puedes recuperarla con una llamada a jobs.get. Por ejemplo, en el siguiente extracto de una respuesta JSON para un trabajo que muestra la consulta de Hamlet de muestra se señala el plan de consulta y la información del cronograma.

"statistics": {
  "creationTime": "1576544129234",
  "startTime": "1576544129348",
  "endTime": "1576544129681",
  "totalBytesProcessed": "2464625",
  "query": {
    "queryPlan": [
      {
        "name": "S00: Input",
        "id": "0",
        "startMs": "1576544129436",
        "endMs": "1576544129465",
        "waitRatioAvg": 0.04,
        "waitMsAvg": "1",
        "waitRatioMax": 0.04,
        "waitMsMax": "1",
        "readRatioAvg": 0.32,
        "readMsAvg": "8",
        "readRatioMax": 0.32,
        "readMsMax": "8",
        "computeRatioAvg": 1,
        "computeMsAvg": "25",
        "computeRatioMax": 1,
        "computeMsMax": "25",
        "writeRatioAvg": 0.08,
        "writeMsAvg": "2",
        "writeRatioMax": 0.08,
        "writeMsMax": "2",
        "shuffleOutputBytes": "18",
        "shuffleOutputBytesSpilled": "0",
        "recordsRead": "164656",
        "recordsWritten": "1",
        "parallelInputs": "1",
        "completedParallelInputs": "1",
        "status": "COMPLETE",
        "steps": [
          {
            "kind": "READ",
            "substeps": [
              "$1:corpus",
              "FROM publicdata.samples.shakespeare"
            ]
          },
          {
            "kind": "AGGREGATE",
            "substeps": [
              "$20 := COUNT($30)",
              "$21 := COUNTIF($31)"
            ]
          },
          {
            "kind": "COMPUTE",
            "substeps": [
              "$30 := 1",
              "$31 := equal($1, 'hamlet')"
            ]
          },
          {
            "kind": "WRITE",
            "substeps": [
              "$20, $21",
              "TO __stage00_output"
            ]
          }
        ]
      },
      {
        "name": "S01: Output",
        "id": "1",
        "startMs": "1576544129465",
        "endMs": "1576544129480",
        "inputStages": [
          "0"
        ],
        "waitRatioAvg": 0.44,
        "waitMsAvg": "11",
        "waitRatioMax": 0.44,
        "waitMsMax": "11",
        "readRatioAvg": 0,
        "readMsAvg": "0",
        "readRatioMax": 0,
        "readMsMax": "0",
        "computeRatioAvg": 0.2,
        "computeMsAvg": "5",
        "computeRatioMax": 0.2,
        "computeMsMax": "5",
        "writeRatioAvg": 0.16,
        "writeMsAvg": "4",
        "writeRatioMax": 0.16,
        "writeMsMax": "4",
        "shuffleOutputBytes": "17",
        "shuffleOutputBytesSpilled": "0",
        "recordsRead": "1",
        "recordsWritten": "1",
        "parallelInputs": "1",
        "completedParallelInputs": "1",
        "status": "COMPLETE",
        "steps": [
          {
            "kind": "READ",
            "substeps": [
              "$20, $21",
              "FROM __stage00_output"
            ]
          },
          {
            "kind": "AGGREGATE",
            "substeps": [
              "$10 := SUM_OF_COUNTS($20)",
              "$11 := SUM_OF_COUNTS($21)"
            ]
          },
          {
            "kind": "WRITE",
            "substeps": [
              "$10, $11",
              "TO __stage01_output"
            ]
          }
        ]
      }
    ],
    "estimatedBytesProcessed": "2464625",
    "timeline": [
      {
        "elapsedMs": "304",
        "totalSlotMs": "50",
        "pendingUnits": "0",
        "completedUnits": "2"
      }
    ],
    "totalPartitionsProcessed": "0",
    "totalBytesProcessed": "2464625",
    "totalBytesBilled": "10485760",
    "billingTier": 1,
    "totalSlotMs": "50",
    "cacheHit": false,
    "referencedTables": [
      {
        "projectId": "publicdata",
        "datasetId": "samples",
        "tableId": "shakespeare"
      }
    ],
    "statementType": "SELECT"
  },
  "totalSlotMs": "50"
},

Usa información de ejecución

En los planes de consultas de BigQuery se proporciona información sobre cómo el servicio ejecuta consultas, pero la naturaleza administrada del servicio limita la practicidad directa de algunos detalles. Muchas optimizaciones se realizan automáticamente cuando usas el servicio, lo que puede diferir de otros entornos en los que el ajuste, el aprovisionamiento y la supervisión pueden requerir personal dedicado y especializado.

Para ver técnicas específicas que pueden mejorar la ejecución de consultas y el rendimiento, consulta la documentación de prácticas recomendadas. El plan de consulta y las estadísticas de cronograma te ayudan a comprender si algunas etapas dominan el uso de recursos. Por ejemplo, una etapa JOIN que genera muchas más filas de salida que filas de entrada indica una oportunidad para aplicar un filtro con anticipación en la consulta.

Además, la información de cronograma puede ayudar a identificar si una consulta determinada es lenta en sí o si lo es debido a los efectos de otras consultas que compiten por los mismos recursos. Si observas que la cantidad de unidades activas es limitada durante toda la vida útil de la consulta, pero que la cantidad de unidades de trabajo en cola es alta, esto podría representar casos en los que reducir la cantidad de consultas simultáneas puede mejorar de manera significativa el tiempo de ejecución general de determinadas consultas.