Pregunta

El resultado explicativo de MySQL es bastante sencillo.El de PostgreSQL es un poco más complicado.Tampoco he podido encontrar un buen recurso que lo explique.

¿Puede describir qué dice exactamente la explicación o al menos indicarme un buen recurso?

¿Fue útil?

Solución

Explicando_EXPLICAR.pdf podría ayudar también.

Otros consejos

La parte que siempre me pareció confusa es el costo inicial versus el costo total.Busco esto en Google cada vez que lo olvido, lo que me trae de regreso aquí, lo que no explica la diferencia, por eso escribo esta respuesta.Esto es lo que he aprendido del Postgres EXPLAIN documentación, explicado tal como lo entiendo.

A continuación se muestra un ejemplo de una aplicación que gestiona un foro:

EXPLAIN SELECT * FROM post LIMIT 50;

Limit  (cost=0.00..3.39 rows=50 width=422)
  ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Aquí está la explicación gráfica de PgAdmin:

graphical explanation of first query

(Cuando usa PgAdmin, puede apuntar el mouse a un componente para leer los detalles del costo).

El costo se representa como una tupla, p.e.el costo de la LIMIT es cost=0.00..3.39 y el costo del escaneo secuencial post es cost=0.00..15629.12.El primer número de la tupla es el costes iniciales y el segundo numero es el coste total.porque usé EXPLAIN y no EXPLAIN ANALYZE, estos costos son estimaciones, no medidas reales.

  • Costes iniciales es un concepto complicado.No solo representa la cantidad de tiempo antes de que ese componente empieza.Representa la cantidad de tiempo entre el momento en que el componente comienza a ejecutarse (leer datos) y el momento en que el componente genera su primera fila.
  • Coste total es el tiempo de ejecución completo del componente, desde que comienza a leer datos hasta que termina de escribir su salida.

Como complicación, los costos de cada nodo "principal" incluyen los costos de sus nodos secundarios.En la representación de texto, el árbol se representa mediante sangría, p. LIMIT es un nodo padre y Seq Scan es su hijo.En la representación de PgAdmin, las flechas apuntan del niño al padre (la dirección del flujo de datos), lo que puede resultar contradictorio si está familiarizado con la teoría de grafos.

La documentación dice que los costos incluyen todos los nodos secundarios, pero observe que el costo total del nodo principal 3.39 es mucho menor que el costo total de su hijo 15629.12.El costo total no es inclusivo porque un componente como LIMIT No es necesario procesar toda su entrada.Ver el EXPLAIN SELECT * FROM tenk1 WHERE unique1 < 100 AND unique2 > 9000 LIMIT 2; ejemplo en Postgres EXPLAIN documentación.

En el ejemplo anterior, el tiempo de inicio es cero para ambos componentes, porque ninguno de los componentes necesita realizar ningún procesamiento antes de comenzar a escribir filas:un escaneo secuencial lee la primera fila de la tabla y la emite.El LIMIT lee su primera fila y luego la emite.

¿Cuándo necesitaría un componente realizar mucho procesamiento antes de poder comenzar a generar filas?Hay muchas razones posibles, pero veamos un ejemplo claro.Aquí está la misma consulta de antes pero ahora contiene un ORDER BY cláusula:

EXPLAIN SELECT * FROM post ORDER BY body LIMIT 50;

Limit  (cost=23283.24..23283.37 rows=50 width=422)
  ->  Sort  (cost=23283.24..23859.27 rows=230412 width=422)
        Sort Key: body
        ->  Seq Scan on post  (cost=0.00..15629.12 rows=230412 width=422)

Y gráficamente:

graphical explanation of second query

Una vez más, el escaneo secuencial en post no tiene costo inicial:comienza a generar filas inmediatamente.Pero este tipo tiene un costo inicial significativo. 23283.24 porque tiene que ordenar toda la tabla antes de que pueda generar incluso una sola fila.El costo total del tipo. 23859.27 es solo un poco más alto que el costo inicial, lo que refleja el hecho de que una vez que se ha ordenado todo el conjunto de datos, los datos ordenados se pueden emitir muy rápidamente.

Observe que el tiempo de inicio del LIMIT 23283.24 es exactamente igual al tiempo de inicio del tipo.Esto no es porque LIMIT En sí mismo tiene un tiempo de inicio alto.En realidad, no tiene tiempo de inicio por sí solo, pero EXPLAIN acumula todos los costos secundarios para cada padre, por lo que el LIMIT El tiempo de inicio incluye la suma de los tiempos de inicio de sus hijos.

Esta acumulación de costos puede dificultar la comprensión del costo de ejecución de cada componente individual.Por ejemplo, nuestro LIMIT tiene un tiempo de inicio cero, pero eso no es obvio a primera vista.Por esta razón, varias otras personas vinculadas a explicar.depesz.com, una herramienta creada por Hubert Lubaczewski (a.k.a.depesz) que ayuda a entender EXPLAIN entre otras cosas, restando los costos de los hijos de los costos de los padres.Menciona algunas otras complejidades en una breve publicación de blog sobre su herramienta.

Se ejecuta desde la mayor sangría hasta la menor sangría, y creo que desde la parte inferior del plan hasta la parte superior.(Entonces, si hay dos secciones sangradas, la que está más abajo en la página se ejecuta primero, luego, cuando se encuentran, se ejecuta la otra, luego se ejecuta la regla que las une).

La idea es que en cada paso haya 1 o 2 conjuntos de datos que lleguen y sean procesados ​​por alguna regla.Si solo hay un conjunto de datos, esa operación se realiza en ese conjunto de datos.(Por ejemplo, escanee un índice para determinar qué filas desea, filtre un conjunto de datos u ordénelo). Si son dos, los dos conjuntos de datos son las dos cosas que tienen mayor sangría y están unidas por la regla que ve.El significado de la mayoría de las reglas se puede adivinar razonablemente fácilmente (especialmente si ha leído un montón de planes explicativos antes), sin embargo, puede intentar verificar elementos individuales ya sea mirando la documentación o (más fácil) simplemente agregando la frase a Google junto con algunas palabras clave como EXPLAIN.

Obviamente, esta no es una explicación completa, pero proporciona suficiente contexto para que puedas descubrir lo que quieras.Por ejemplo, considere este plan de una base de datos real:

explain analyze
select a.attributeid, a.attributevalue, b.productid
from orderitemattribute a, orderitem b
where a.orderid = b.orderid
and a.attributeid = 'display-album'
and b.productid = 'ModernBook';

------------------------------------------------------------------------------------------------------------------------------------------------------------

 Merge Join  (cost=125379.14..125775.12 rows=3311 width=29) (actual time=841.478..841.478 rows=0 loops=1)
   Merge Cond: (a.orderid = b.orderid)
   ->  Sort  (cost=109737.32..109881.89 rows=57828 width=23) (actual time=736.163..774.475 rows=16815 loops=1)
         Sort Key: a.orderid
         Sort Method:  quicksort  Memory: 1695kB
         ->  Bitmap Heap Scan on orderitemattribute a  (cost=1286.88..105163.27 rows=57828 width=23) (actual time=41.536..612.731 rows=16815 loops=1)
               Recheck Cond: ((attributeid)::text = 'display-album'::text)
               ->  Bitmap Index Scan on (cost=0.00..1272.43 rows=57828 width=0) (actual time=25.033..25.033 rows=16815 loops=1)
                     Index Cond: ((attributeid)::text = 'display-album'::text)
   ->  Sort  (cost=15641.81..15678.73 rows=14769 width=14) (actual time=14.471..16.898 rows=1109 loops=1)
         Sort Key: b.orderid
         Sort Method:  quicksort  Memory: 76kB
         ->  Bitmap Heap Scan on orderitem b  (cost=310.96..14619.03 rows=14769 width=14) (actual time=1.865..8.480 rows=1114 loops=1)
               Recheck Cond: ((productid)::text = 'ModernBook'::text)
               ->  Bitmap Index Scan on id_orderitem_productid  (cost=0.00..307.27 rows=14769 width=0) (actual time=1.431..1.431 rows=1114 loops=1)
                     Index Cond: ((productid)::text = 'ModernBook'::text)
 Total runtime: 842.134 ms
(17 rows)

Intente leerlo usted mismo y vea si tiene sentido.

Lo que leí es que la base de datos primero escanea el id_orderitem_productid índice, usándolo para encontrar las filas que desea orderitem, luego ordena ese conjunto de datos usando una clasificación rápida (la clasificación utilizada cambiará si los datos no caben en la RAM), luego lo deja a un lado.

A continuación, escanea orditematt_attributeid_idx para encontrar las filas que quiere orderitemattribute y luego ordena ese conjunto de datos mediante una clasificación rápida.

Luego toma los dos conjuntos de datos y los fusiona.(Una unión de fusión es una especie de operación de "compresión" en la que recorre los dos conjuntos de datos ordenados en paralelo, emitiendo la fila unida cuando coinciden).

Como dije, trabajas a través del plan desde la parte interior a la parte exterior, de abajo hacia arriba.

También hay una herramienta de ayuda en línea disponible. Depesz, que resaltará dónde están las partes costosas de los resultados del análisis.

también tiene uno, aquí está el mismos resultados, lo que para mí deja más claro dónde está el problema.

Administrador de páginas Le mostrará una representación gráfica del plan explicativo.Alternar entre los dos realmente puede ayudarte a comprender lo que significa la representación del texto.Sin embargo, si sólo quiere saber qué va a hacer, es posible que pueda utilizar siempre la GUI.

Documentación oficial de PostgreSQL proporciona una explicación interesante y exhaustiva sobre cómo entender el resultado de la explicación.

Si instala pgadmin, hay un botón Explicar que, además de mostrar la salida de texto, dibuja diagramas de lo que está sucediendo, mostrando los filtros, clasificaciones y combinaciones de subconjuntos que encuentro realmente útiles para ver qué está sucediendo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top