Anda di halaman 1dari 89

Optimizacin de Consultas

Optimizacin de Consultas
Trataremos de Orientarlo a Desarrolladores
Es un tema que tiene muchos Sub-temas
Algunos subtemas estn fuera del scope de tareas
de un desarrollador.
Configuracin de Posgresql,
Analyze (actualizar estadsticas)
Vamos a ver:
Algunas formas de monitorear queries
Explain y Explain/Analyze
Algunos ejemplos de queries y como los optimizamos
Optimizacin de Consultas
Conceptos Generales
Antes de ir a Postgres, veamos algo general de ndices y del optimizador
Trade off Teora / Prctica
Explain y Explain Analyze
Explain = Plan de Acceso + Pronstico
Explain Analyze = Plan de Acceso + Pronstico + Realidad
Tipos de Accesos de Postgres
Sequencial, Indexado, Mltiple Indice, Nested Loop Join, Hash Join,
Subqueries correlacionados
Monitoreo de queries
Psql (poco pgadminIII)

Formas de JOIN
JOIN Tradicional, INNER JOIN, OUTER JOIN
Que diferencias hay ?
Es alguno ms performante ?
Optimizacin de Consultas - Indices
Indices Btree+ Soportan eficientemente bsquedas por igualdad y rangos
Where legajo = 123
Where salario > 8000
Son los ms usados (en Postgres y otras bases)
Existen otros tipos de ndices (R-Tree,hash,Gin)

Indice Btree

Legajo Nombre Materia salario

Cmo sera un ndice cuya clave


admite duplicados ?
Podemos tener varios ndices

HAY QUE ELEGIR UNO. Cmo lo elegimos ?


Conceptos Generales a todos los RDBMS
El optimizador (planner)
Input: Query, Estadsticas
Output: Plan de Acceso (Supuestamente el Optimo)
El query se ejecuta de acuerdo al Plan de Acceso, su tiempo de
ejecucin vara dependiendo de haber elegido un buen plan

El optimizador funciona como una


caja negra, No podemos
configurarlo. Sin embargo:
Algunos motores soportan Directivas
(Informix SI, Postgres NO)
Existen algunos parmetros que
afectan su funcionamiento
Tiempo de Optimizacin
(eleccion del plan de Tiempo de Ejecucin
acceso optimo)

Tiempo Total del Query


Optimizador basado en costos (1/3)
SELECT T1.A, T1.B, T2.C, T2.D Indices Disponibles:
FROM T1, T2 Ninguno
WHERE T1.A = T2.A and T1.E > 100 AND T2.F = 06-04-2014

Plan 1 Plan 2 Plan


C. Total: 6800 C. Total: 3100 Optimo
Filtro de T1.E > 100 and Junta por Hash join
T2.F=06-04-2014 T1.A =T2.A
Costo: 300 Costo: 1000

Junta por Hash join Filtro de T1.E


> 100 Filtro T2.F=06-04-2014
T1.A =T2.A
Costo: 400 Costo: 200
Costo: 5000

Acceso Acceso Acceso Acceso


Seq T1 Seq T2 Seq T1 Seq T2
Costo:1000 Costo:500 Costo:1000 Costo:500

Tiempo de Optimizacin
(eleccion del plan de Tiempo de Ejecucin
acceso optimo)
Los costos son valores arbitrarios
para que cierre el ejemplo (puede
Tiempo Total del Query haber inconsistencias)
Optimizador basado en costos (2/3)
SELECT T1.A, T1.B, T2.C, T2.D Indices Disponibles:
FROM T1, T2 Ix1: clave T2.A
WHERE T1.A = T2.A and T1.E > 100 AND T2.F = 06-04-2014

TENEMOS UN INDICE Plan 3 Plan 4 Plan


A LOS PLANES C. Total: 1900 C. Total: 1650 Optimo
ANTERIORES SE Filtro T2.F=06-04-2014
AGREGAN ALGUNOS Filtro de T1.E > 100 and Costo: 50
MAS T2.F=06-04-2014
Costo: 300 Junta por Nested Loop
join T1.A =T2.A
Plan 1 Costo: 200
Junta por Nested Loop
C. Total: 6800 Join T1.A =T2.A Filtro de T1.E
Costo: 600 > 100
Plan 2 Costo: 400
C. Total: 3100
Acceso
Seq T1
Acceso
Costo:1000
Seq T1
Costo:1000
Tiempo de Optimizacin
(eleccion del plan de Tiempo de Ejecucin
acceso optimo)
Los costos son valores arbitrarios
para que cierre el ejemplo (puede
Tiempo Total del Query haber inconsistencias)
Optimizador basado en costos (3/3)
SELECT T1.A, T1.B, T2.C, T2.D Indices Disponibles:
FROM T1, T2 Ix1: clave T2.A
WHERE T1.A = T2.A and T1.E > 100 AND T2.F = 06-04-2014 Ix2: clave T1.E

TENEMOS DOS
INDICES A LOS
Plan
Plan 5 Optimo
PLANES ANTERIOES
C. Total: 350
SE AGREGAN
ALGUNOS MAS Filtro T2.F=06-04-2014
Costo: 100
Plan 1 Plan 4
C. Total: 6800 C. Total: 1650
Junta por Nested Loop
Join T1.A =T2.A
Plan 2 Costo: 200
C. Total: 3100
Plan 3 Filtro T1.E > 100 via
C. Total: 1900 Indice T1.E
Costo:50
Tiempo de Optimizacin
(eleccion del plan de Tiempo de Ejecucin
acceso optimo)
Los costos son valores arbitrarios
para que cierre el ejemplo (puede
Tiempo Total del Query haber inconsistencias)
Index Matching Ejemplos
Tabla negocio.sga_alumnos
Alumno legajo Propuesta Plan_version ubicacion Modalidad Division Anio_cursada readmisiones Regular calidad

Dado el query:
SELECT * FROM sga_alumnos Claves de Indices
WHERE legajo = 1111 en sga_alumnos
Legajo
AND modalidad = P
Persona
Calidad
De los ndices que existen cuales puedo usar el planner ? Modalidad
Puedo usar idx Es bueno ? Comentarios Plan version
legajo Si !! Trae 1 fila, y luego verifico el filtro Propuesta
de modalidad = P Ubicacion
modalidad Maso Trae muchas filas y luego en cada Persona, propuesta
una verifico el filtro legajo = 1111

Hay algn ndice para crear que pueda mejorar ? NO


Index Matching Ejemplos
Tabla negocio.sga_alumnos
Alumno legajo Propuesta Plan_version ubicacion Modalidad Division Anio_cursada readmisiones Regular calidad

Dado el query:
Claves de Indices
SELECT * FROM sga_alumnos en sga_alumnos
Legajo
WHERE modalidad = P
Persona
AND anio_cursada = 2014 Calidad
Modalidad
De los ndices que existen cuales puedo usar ? Plan version
Puedo usar idx Es bueno ? Comentarios Propuesta
modalidad Maso Trae muchas filas y luego en cada una Ubicacion
verifico el filtro anio_cursada = 2014
Persona, propuesta
Hay algn ndice para crear que pueda mejorar ?
Puedo usar idx Es bueno ? Comentarios
Anio_cursada Si (no es Trae algunas filas y luego en cada
super) una verifico el filtro modalidad = P
Index Matching Ejemplos
Tabla negocio.sga_alumnos
Alumno legajo Propuesta Plan_version ubicacion Modalidad Division Anio_cursada readmisiones Regular calidad

Dado el query:
Claves de Indices
SELECT * FROM sga_alumnos en sga_alumnos
Legajo
WHERE legajo > 0
Persona
AND apellido = Perez Calidad
Modalidad
De los ndices que existen cuales puedo usar ? Plan version
Puedo usar idx Es bueno ? Comentarios Propuesta
legajo Malo Trae todas las filas y luego en cada Ubicacion
(con >0) una verifico el filtro apellido = Perez
Persona, propuesta
Apellido mejor Trae solo los Perez
apellido

Hay algn ndice para crear que pueda mejorar ? NO


Indices Redundantes
Daad la Tabla T1 (A, B, C, D, E, F)

INDICE compuesto con clave (A, B, C)


INDICE con clave (A)
INDICE con clave (B)
INDICE con clave (C )
Monitoreo de Queries
Pg_stat_activity
Foto de los queries en ejecucin en un instante dado
Pg_stat_statement
Podemos tener un poco de historia de queries
ejecutados y agruparlos por query, junto con algunas
estadsticas
Log de Postgres
Podemos pedir a postgres que logee queries que
demoren mas de x miliseg.
Pg_stat_activity (1/1)
La tabla pg_stat_activity nos muestra los queries
actualmente en ejecucin.
Se puede calcular el tiempo que lleva corriendo !

Queda para otra oportunidad ver como se activa. Naturalmente en produccin debera
desactivarse.
Postgres Query Log (1/1)
Para activarlo es necesario configurar el SQL query
logging, en el postgresql.conf con el parmetro :
0 Indica loggear todos los queries.
-1 deshabilita el log.
log_min_duration_statement = 0 otro valor (ej.300) solo logea
aquellos queries cuya duracin
exceda 300 milisegundos.
Pg_stat_statements (1/5)
Extension para agrupar los queries que recibe la base
Permite conocer de cada query:
Cuntas veces se lo ejecuta,
Cunto tiempo acumulan todas sus ejecuciones
Se instala asi:
1- Modificar parmetro en el postgresql.conf
shared_preload_libraries = 'pg_stat_statements'
2- Bajar y subir postgres
3- En la base de datos que deseo monitorear ejecutar:
CREATE extension pg_stat_statements;

Las estadsticas recolectadas por este mdulo estarn en


la vista pg_stat_statements. Esta vista contiene una fila
por cada query distinto, database ID, y user ID
Pg_stat_statements (2/5)
SELECT left(query, 50),
round(sum(total_time/1000)::numeric, 6) as sum,
round((sum(total_time/1000)/sum(calls))::numeric, 6) as average,
sum(calls) as cuantas,
round(100.0*(sum(total_time/tot))::numeric, 2) as percent
FROM (select sum(total_time) as "tot "
from pg_stat_statements) asx, pg_stat_statements
group by query
order by sum(total_time) desc limit 10;
Pg_stat_statements (3/5)
TABLA pg_stat_statements
Pg_stat_statements (4/5)
Pg_stat_statements (5/5)

en el postgresql.conf
Monitoreo de Queries
Conclusiones
Ventajas Desventajas
Pg_stat_activity Facil de Usar Es una foto de los queries en
ejecucin.No tiene los
queries que ya terminaron
LOG de postgres Podemos ver la historia, los Requiere un poco de
queries que ya terminaron, y configuracin y buscar en el
su duracin. log generado por postgres.
Queries rpidos que se
ejecutan muchas veces, no
los veo
Pg_stat_statement Muestra historia y queries Requiere configurar y agregar
actuales. Incluye la cantidad una extensin en la base de
de veces que se ejecut un datos. Y ejecutar un query
query y duracin total. para obtener los resultados
Puede detectar queries
relativamente rpidos que se
ejecutan muchas veces
Anlisis de Queries
Arranquemos con casos de una sola tabla para
graficar algunas ideas:
SELECT * FROM mdp_personas WHERE email_valido = 1
SELECT * FROM mdp_personas WHERE apellido = Perez
Como ya vimos Postgres tiene 2 formas de
acceder a mdp_personas:
Secuencial (no es bueno, pero a veces no queda otra)
Usando un Indice (si existe alguno que le sirva)
Existen varias formas de usar ndices para acceder a tablas
Cuando el query tiene varias tablas se combinan !!
EXPLAIN de Queries
Si anteponemos EXPLAIN al query vemos el plan de acceso
generado por el planner (solo pronsticos, no ejecuta el query)
SELECT * FROM mdp_personas WHERE email_valido = 0

SELECT * FROM mdp_personas WHERE apellido = Servat


EXPLAIN ANALIZE de Queries
Si usamos EXPLAIN ANALYZE vemos el plan de acceso (solo
pronsticos ) + algunas mtricas de la ejecucin (ejecuta el query)
SELECT * FROM mdp_personas WHERE email_valido = 0
SELECT * FROM mdp_personas WHERE apellido = Servat
Anlisis de Queries
Ejemplo de Acceso Indexado + Filtro por otra Columna
EXPLAIN select * from CENSO2012
where DNI_TITULAR = 14345550
AND CODPOSTAL = 9993;

Que hubiera pasado si existieran 2 ndices: uno por dni y otro por codpostal ?
- 2 Posibles Planes de acceso. Cual es el menos costoso en trminos de lectura ?
- Habr alguna otra forma de acceder por ndice cuando hay 2 ndices?.
Ejemplo Where nombre = juan and codpostal = 1661
Plan-reading is an art that deserves an extensive tutorial, which this is not; but
here is some basic information.
Anlisis de Queries
Acceso por indice, filtrando por otra condicion
(Similar al anterior) y luego con un sort
Tambin lo tenemos en formato grafico en el
PGAdminIII
Bitmap Index Scan

Aqu el optimizador decidi usar un plan de 2 pasos: El plan interno, utiliza el


ndice para encontrar la ubicacin de las filas que matchean con la condicin
(unique1 < 100), como son varias filas, arma un plan externo que se encarga de
hacer el fetch de las filas.
La razn para hacerlo en 2 pasos es que en el plan externo las filas a acceder se re-
ordenan de acuerdo a su posicin fsica en disco antes de leerse, para asi
minimizar el costo de hacer fetchs separados. The "bitmap" mentioned in the
node names is the mechanism that does the sorting.
Mltiples Indices
EXPLAIN select * from CENSO2012
where APELLIDO = PEREZ
OR CODPOSTAL = 9993;
Si Tenemos un ndice (apellido, codpostal) No nos sirve ya que tendremos
que leer secuencialmente toda la tabla para verificar CODPOSTAL=9993
Si tenemos 2 indices: ix1(apellido) y ix2(codpostal) PostgreSQL tiene la
capacidad de hacer mltiples index scans a una misma tabla, guardar sus
resultados y luego combinarlos (mediante AND o OR )

To combine multiple indexes, the system scans each needed index and prepares a bitmap in memory giving the locations of table rows that are reported as matching that
index's conditions. The bitmaps are then ANDed and ORed together as needed by the query. Finally, the actual table rows are visited and returned. Por ejemplo: Un qury con
WHERE x = 42 OR x = 47 OR x = 53 OR x = 99 could be broken down into four separate scans of an index on x, each scan using one of the query clauses. The results of these
scans are then ORed together to produce the result.
Si tenemos 2 indexes uno con clave x y el otro con clave y . Un query con WHERE x = 5 AND y = 6 puede hacer 2 index scans en cada indice y luego combinar los resultados
mediante un AND.
Indices Funcionales
SELECT codpostal FROM LOCALIDADES
WHERE upper(nombre) = MAR DEL PLATA

 Si tuvieramos este ndice no lo usara:


CREATE INDEX nosirve ON LOCALIDADES (nombre);

 En cambio este ndice si va a ser usado


CREATE INDEX sirve ON LOCALIDADES (upper(nombre));
Indices Funcionales
Cualquier operacin que le hagamos a una columna indexada
impide que se use el ndice
En general si tenemos una expresin en el WHERE que aparece
con frecuencia deberamos considerar un ndice funcional
explain analyze select numero_cargo from rrhh_cargos where cod_rrhh_importacion = 6656;
explain analyze select numero_cargo from rrhh_cargos where cod_rrhh_importacion - 2 = 6654 ;

QUERY PLAN
---------------------------------------------------------------------------------
Bitmap Heap Scan on rrhh_cargos (cost=851.82..64504.40 rows=48943 width=6)
(actual time=24.000..184.007 rows=46974 loops=1)
Recheck Cond: (cod_rrhh_importacion = 6656)
-> Bitmap Index Scan on rrhh_cargos_imp (cost=0.00..839.58 rows=48943
width=0) (actual time=20.000..20.000 rows=46974 loops=1)
Index Cond: (cod_rrhh_importacion = 6656)
Total runtime: 312.010 ms
QUERY PLAN
---------------------------------------------------------------------------------
Seq Scan on rrhh_cargos (cost=0.00..105526.25 rows=13646 width=6) (actual
time=360.011..2176.070 rows=46974 loops=1)
Filter: ((cod_rrhh_importacion - 2) = 6654)
Total runtime: 2204.071 ms
Indices Funcionales Un EjemploReal
Dado este query

 Si tuvieramos este ndice no lo usara:


CREATE INDEX idx_documento_cargo ON rrhh_cargos USING btree
(cod_rrhh_importacion, cuil_cuit);

 En cambio este ndice si va a ser usado


CREATE INDEX idx_documento_cargo ON rrhh_cargos USING btree
(cod_rrhh_importacion, "substring"((cuil_cuit)::text, 3, 8));
Optimizacion con Subqueries
Evitar Queries correlacionados (si es posible)
Si no es posible evitarlo, revisar si le falta algun ndice (vamos a ver un
ejemplo)
Subqueries en el from no tienen ndices
A veces es ms conveniente agregar un subquery en el FROM.
Otras veces puede ser necesario crear una temporal previamente , inclusive se
puede crear ndices a las temporales
En lo posible Aplanar subqueries (usando joins en lugar de subqueries,
aunque no siempre es posible)
Optimizacion con Subqueries
Un subquery NO Correlacionado no referencia ninguna columna del query
externo y por lo tanto tendr un resultado constante. El SubQuery se
SELECT FROM sga_alumnos Ejecuta 1 vez

WHERE persona IN (SELECT persona FROM mdp_personas


WHERE apellido = Perez);

Un subquery Correlacionado hace referencia a alguna columna del query


externo, y por lo tanto se debe ejecutar una vez por cada fila candidata del
query externo.
El SubQuery se Ejecuta
N veces. 1 vez por cada
row en Materia
SELECT nombre FROM materias mat candidata al resultado

WHERE 0 = (selec count(*) FROM cursa


WHERE cursa.materia_id = mat.materia_id)
Subquery Correlacionado (Caso real 1/5) El SubQuery se
Ejecuta 1 vez por
cada fila del query
externo

http://comunidad.siu.edu.ar/foro/index.php?topic=8823
Subquery Correlacionado (Caso real) 2/5
Subquery Correlacionado (Caso real) 3/5
Subquery Correlacionado (Caso real 4/5)
Subquery Correlacionado (Caso real 5/5)
COMPARANDO LOS EXPLAINS DE (USANDO www.explain.depesz.com)
SIN INDICE

CON INDICE
REVISAR SI VA !!Aplanar
subqueries(FROM-list subquery example)
El optimizador puede cambiar el query internamente
SELECT *
FROM t1, (SELECT * FROM t2 WHERE t2.x = 10) t2
WHERE t1.id = t2.id;
-- converted by the optimizer into
SELECT *
FROM t1, t2
WHERE t1.id = t2.id and t2.x = 10
Juntas
Si tenemos una junta entre 2 tablas con una
condicion de junta T1.A = T2.B
Es conveniente tener 2 ndices: T1(A) y T2(B)
El optimizador usar uno solo, pero tendr ms
opciones o planes para analizar
Postgres tiene 3 tcnicas o mecanismos para
resolver las JUNTAS:
NESTED LOOP JOIN
HASH JOIN
SORT MERGE JOIN
SI no hay ndices, Postgres deber usar HASH o
SORT MERGE.
Juntas
SELECT * FROM T1, T2
WHERE T1.PK = T2.FK
Tipos de Joins
Nestloop: Es el ms utilizado. Primero recorre una tabla (T1) y por cada fila ,
busca en la segunda tabla (T2) (usando un ndice) las filas que cumplen
T2.FK = T1.PK
Merge: Ambas tablas son ordenadas por las columnas del JOIN (T1.PK y
T2.FK) y luego se scanean en paralelo y se detectan las filas que hacen
JOIN (No es performante, revela falta de ndices)
Hash: Una de las tablas se scanea y se crea una tabla de HASH, usando las
columnas del JOIN como claves de HASH. Luego la otra tabla se escanea
y se aplica la funcion de HASH a las columnas del JOIN, con ese
resultado se busca en la tabla de HASH las filas que hacen JOIN (No es
performante, revela falta de ndices)
SET enable_nestloop = off; --permite ver q se hara en otro caso
SET enable_hashjoin = off;
SET enable_mergejoin= off;
Juntas

EXPLAIN ANALYZE select * from CENSO2012 C, Localidades L


where L.codpostal = C.codpostal
and L.nombre = localidad2341;
Juntas
 Hash Join
 (ejecutamos el mismo query pero sin ndices)
EXPLAIN ANALYZE select * from CENSO2012 C, Localidades L
where L.codpostal = C.codpostal
and L.nombre = localidad2341;
JOINS - INNER Vs JOIN Tradicional
select *
FROM PERSONAS P, LOCALIDAD L
WHERE L.codpostal = P.codpostal
and L.nombre = localidad2341;

select *
FROM PERSONAS P INNER JOIN LOCALIDAD L ON L.codpostal = P.codpostal
WHERE L.nombre = localidad2341;

select *
FROM PERSONAS P INNER JOIN LOCALIDAD L USING (codpostal)
WHERE L.nombre = localidad2341;

select *
FROM PERSONAS P NATURAL JOIN LOCALIDAD L
WHERE L.nombre = localidad2341;

Estos Joins son todos equivalentes.


El ON es para especificar la condicin de JOIN
El USING es para indicar las Columnas de condicin de JOIN, si tienen el mismo nombre en ambas tablas
El NATURAL indica que la junta es por todas las columnas de igual nombre en ambas tablas
EL ON / USING / NATURAL se pueden usar en INNER o en OUTER joins
Outer Vs Inner Join
INNER = Equivalente al Join standard . Todas las tuplas del
resultado se forman mediante 2 partes que se juntan.
OUTER = Una de las tablas puede no tener una tupla contraparte

El uso del OUTER puede imponer un orden en la forma que se accede a tablas. Por ejemplo si tenemos

SELECT * FROM A LEFT OUTER JOIN (B join C on (b.ref = c.id) ) ON (A.id = B.id)
Tiene que resolver el primero el JOIN entre B y C y luego el JOIN entre A y B+C

SELECT * FROM A, B, C WHERE A.id = B.id AND B.ref = C.id


Tiene que evaluar todos los posibles ordenes: A,B,C o A,C,B o B,C,A o . (6 ordenes posibles)

En este tutorial : http://www.postgresql.org/docs/9.3/static/tutorial-join.html


no hay ninguna mencion a que el INNER JOIN es mas performante q el JOIN tradicional usando el WHERE
Demo 1 Subquery Correlacionado El SubQuery se
Ejecuta 1 vez por
cada fila del query
externo

http://comunidad.siu.edu.ar/foro/index.php?topic=8823
Demo 1 Subquery Correlacionado

cd /home/demo/test/mapuche
Ejecutamos ./q1.sh y vemos la salida
Ejecutamos time ./q1.sh y vemos cuanto demora
Ejecutamos ./qex1.sh y vemos que el Subplan se
resuelve con una busqueda sequencial.
More creaidx.sh para ver el indice que vamos a crear
Ejecutamos ./creaidx.sh y creamos el indice
Ejecutamos ./q1.sh y vemos que trae las mismas filas
pero ms rpido
Ejecutamos time ./q1.sh y comparamos los tiempos
Demo2 Queries en el FROM (qry_dnp_mal.sh) 1 Vez por Row
Demo2 Queries en el FROM (qry_dnp_ok.sh)
1 Vez por query. (No
es correlacionado)
Demo 2 Uso de Queries en el FROM

cd /home/demo/test/pilaga
Ejecutamos ./qry_dnp_mal.sh y vemos la salida
Ejecutamos time ./qry_dnp_mal.sh y vemos cuanto demora
Ejecutamos time ./qry_dnp_ok.sh y vemos cuanto demora.
Ejecutamos time ./qry_dnp_ok.sh > /dev/null y vemos cuanto
demora. La diferencia es el trafico de las filas
Ejecutamos time ./qry_exp_dnp_mal.sh y vemos cuanto demora
Ejecutamos time ./qry_exp_ana_dnp_mal.sh y vemos cuanto
demora
guarani_3_10=# \d test;
Tabla public.test
Columna | Tipo | Modificadores
---------+-----------------------------+---------------
nombre | character varying(30) |
nacim | timestamp without time zone |
ndices:
"testix1" btree (nacim)

guarani_3_10=# explain select nombre from test where nacim = '02-07-2015';


QUERY PLAN
----------------------------------------------------------------------------
Index Scan using testix1 on test (cost=0.29..4.30 rows=1 width=10)
Index Cond: (nacim = '2015-07-02 00:00:00'::timestamp without time zone)
(2 filas)

guarani_3_10=# select nombre from test where nacim = '02-07-2015' ;


nombre
--------
(0 filas)

guarani_3_10=# select nombre,nacim from test where nacim::date = '02-07-2015' limit 3 ;


nombre | nacim
---------+----------------------------
nombre1 | 2015-07-02 10:46:41.692558
nombre2 | 2015-07-02 10:46:41.692558
nombre3 | 2015-07-02 10:46:41.692558
(3 filas)

guarani_3_10=# explain select nombre,nacim from test where nacim::date = '02-07-2015' limit 3 ;
QUERY PLAN
--------------------------------------------------------------
Limit (cost=0.00..12.54 rows=3 width=18)
-> Seq Scan on test (cost=0.00..209.00 rows=50 width=18)
Filter: ((nacim)::date = '2015-07-02'::date)
(3 filas)

guarani_3_10=# explain select nombre,nacim from test where nacim::date = '02-07-2015' ;


QUERY PLAN
--------------------------------------------------------
Seq Scan on test (cost=0.00..209.00 rows=50 width=18)
Filter: ((nacim)::date = '2015-07-02'::date)
(2 filas)
Gracias !!
Anlisis de Consultas

EXPLAIN [ ANALYZE ] statement


 Ejemplo

EXPLAIN ANALYZE select * from dh01 where tipo_sexo='M';

Seq Scan on dh01 (cost=0.00..242.00 rows=4285 width=200)


(actual time=0.033..18.091 rows=4336 loops=1)
Filter: (tipo_sexo = 'M'::bpchar)
Total runtime: 29.143 ms

 cost -> costo en traer una pagina (constante 1.0 en seq scan)
 rows -> en filas
 width -> en bytes
Anlisis de Consultas
Ejemplo de barrido Secuencial
(Los barridos secuenciales suelen ser ineficientes, recorren toda la tabla)

EXPLAIN select * from CENSO2012 where DNI_TITULAR = 10499752;

 cost -> costo en traer una pagina (constante 1.0 en seq scan)
 rows -> en filas
 width -> en bytes

Query1.sql
ndices
 En las hojas del rbol el optimizador debe decidir
cual es la mejor forma de acceder a cada tabla
 Barrido Secuencial ?
 Acceso Indexado ?
 Qu ndices me permite usar Postgres ?
CREATE [ UNIQUE ] INDEX [CONCURRENTLY] name ON table
[USING method] ({ column | ( expression )}
[WITH (storage_parameter = value [, ... ] )]
[TABLESPACE tablespace ]
[ WHERE predicate ]
ndices (7)

CREATE [ UNIQUE ] INDEX [CONCURRENTLY] name ON table


[USING method] ({ column | ( expression )}
[WITH (storage_parameter = value [, ... ] )]
[TABLESPACE tablespace ]
[ WHERE predicate ]

 Mtodos posibles para el armado del ndice


 B-tree
 R-tree
 Hash
Indices GiST y GIN orientados para Full Text Search.
 GiST R-tree: two-dimensional spatial data
 GIN Hash: solo para = searchs / No WAL logged
Indices Btree (rbol B+)
401

Estructuras de datos 394


393

Arbol B+ > 387


D

387 294 A
> 293

292 292
T
97
O
95

292 S
89
89
59
57
56

Nivel 0 Nivel 1 Nivel 2


ndices B-tree
 Es el tipo de ndice que utiliza PostgreSQL por defecto.
 Es el utilizado por las PRIMARY KEY (claves primarias) en su creacin.
 Es el nico tipo de ndice que soporta la clausula UNIQUE

 Usado en bsquedas por = y por < , <= , > , = >


 Implementacin de arboles B de alta concurrencia (Lehman Yao)
 Maneja solamente bsquedas por rango de una dimensin.
 Es el nico (junto con GiST) que soporta indexado por
mltiples columnas.
Anlisis de Consultas
 Ejemplo de Acceso Indexado
 Creamos un ndice por DNI_TITULAR

EXPLAIN select * from CENSO2012 where DNI_TITULAR = 10499752;

 cost -> costo de i/o + costo de procesamiento


 rows -> en filas
 width -> en bytes

Query1.sql
Anlisis de Consultas
 Acceso Index Bitmap
 Puede acceder a una tabla usando 2 ndices, luego obtener la
interseccin de los punteros
EXPLAIN ANALYZE select * from CENSO2012 where nacimiento=14-01-1995
and codpostal = 9993;

Query3.sql
Anlisis de Consultas
Acceso Index Bitmap
Cuando se accede a una tabla por un ndice, y se espera que
muchas filas sean recuperadas, es conveniente partir el
acceso a la tabla en 2 etapas:
Acceder primero por el ndice recuperando todos los punteros a las filas.
Ordenar dichos punteros de acuerdo a la posicin fsica de la fila a recuperar
EXPLAIN ANALYZE select * from CENSO2012 where nacimiento=14-01-1995;

Query3.sql
EXPLAIN Vs EXPLAIN ANALYZE
El mismo query ejecutado con EXPLAIN y con EXPLAIN ANALYZE
Costo en unidades tericas Tiempo de ejecucin en mseg
Anlisis de Consultas
SELECT * FROM T1, T2
WHERE T1.PK = T2.FK
Tipos de Joins
Nestloop: Es el ms utilizado. Primero recorre una tabla (T1) y por cada fila ,
busca en la segunda tabla (T2) (usando un ndice) las filas que cumplen
T2.FK = T1.PK
Merge: Ambas tablas son ordenadas por las columnas del JOIN (T1.PK y
T2.FK) y luego se scanean en paralelo y se detectan las filas que hacen
JOIN (No es performante, revela falta de ndices)
Hash: Una de las tablas se scanea y se crea una tabla de HASH, usando las
columnas del JOIN como claves de HASH. Luego la otra tabla se escanea
y se aplica la funcion de HASH a las columnas del JOIN, con ese
resultado se busca en la tabla de HASH las filas que hacen JOIN (No es
performante, revela falta de ndices)
SET enable_nestloop = off; --permite ver q se hara en otro caso
SET enable_hashjoin = off;
SET enable_mergejoin= off;
Anlisis de Consultas
 Nested Loop Join

EXPLAIN ANALYZE select * from CENSO2012 C, Localidades L


where L.codpostal = C.codpostal
and L.nombre = localidad2341;
Anlisis de Consultas
 Hash Join
 (ejecutamos el mismo query pero sin ndices)
EXPLAIN ANALYZE select * from CENSO2012 C, Localidades L
where L.codpostal = C.codpostal
and L.nombre = localidad2341;
Creacin de FKs
 Deben REFERENCIAR a una tabla/columna(s) que
sean PK o UNIQUE
 La restriccin del punto anterior nos asegura que
en la tabla REFERENCIADA habr un ndice
CREATE TABLE propietario (
dni integer ,
apellido char(20)
);
alter table propietario add constraint prop_pk primary key(DNI);

CREATE TABLE vehiculos(


patente char(6),
marca smallint,
modelo smallint,
color smallint,
dni_propietario integer
);
alter table vehiculos add constraint vehic_pk primary key(patente);
alter table vehiculos add constraint prop_fk foreign key (dni_propietario) references propietario(dni);
Control de la Integridad Referencial

 Se realiza mediante triggers


 Son creados automticamente al definir las FKs

CREATE TABLE propietario (


dni integer ,
apellido char(20)
);
alter table propietario add constraint prop_pk primary key(DNI); Tenemos
Indices Aqu
CREATE TABLE vehiculos(
patente char(6),
marca smallint,
modelo smallint,
color smallint,
dni_propietario integer
);
alter table vehiculos add constraint vehic_pk primary key(patente);
alter table vehiculos add constraint prop_fk foreign key (dni_propietario) references propietario(dni);

Notar que si por algn motivo tenemos que buscar por dni_propietario en vehculos,
no tenemos un ndice
Control de la Integridad Referencial
 Los INSERT en vehculo tienen que verificar si
Existe el DNI en propietario, para lo cual tienen un
ndice (la PK)
 Los DELETES en propietario tienen que verificar si
Existe alguna referencia a la fila a borrar en
vehculo, para lo cual NO hay un ndice
 Los DELETES en propietario se pueden volver
muuuy lentos, si tenemos muchas filas en
vehculos.
Control de la Integridad Referencial
EJEMPLO: Un DELETE que borra 5000 filas tarda 8 minutos,
porque tiene que validar la FK y no tiene ndice.
Control de la Integridad Referencial
 Alternativas para acelerar que los DELETES en
propietario
 Le ponemos un ndice a vehculos
 Desactivamos las FKs durante el DELETE
 Varias FORMAS de desactivar las constraints:
 PONER LA EN MODO DEFERED (difiere el control al momento del
commit)
 DROPEAR y RECREAR CONSTRAINT (controla la FK al recrearla)
 DESHABILITAR LOS TRIGGERS (no se controla la FK mientras se
deshabilitan)
 alter table propietario disable trigger all
 antes de 8.1 hacer un:
update pg_class set reltriggers=0 where relname = propietario';
Control de la Integridad Referencial
Si desactivamos los trigggers antes, el DELETE se ejecuta en
0.5 segs. Pero no se controla la FK durante el DELETE
Control de la Integridad Referencial

Borrando y re-creando la
FK. EL Delete tarda 1.5
seg. Al recrear la FK
controla que los datos
existentes la cumplan. La
tabla con la FK tiene
500.000 filas
Window Functions
Son funciones similares a las funciones de agregacin. Pero tienen la
ventaja de que NO obligan a agrupar filas (mediante group by) en una
sola fila. As cada fila es independiente de las demas, aunque la window
function claramente acceder a otras filas aparte de la row corriente para
hacer sus clculos
En el ejemplo vemos que tenemos el promedio de salario por depto, junto
con los datos de cada empleado. Con un group by no podriamos
obtenerlo ya que deberiamos agrupar por deptname y no podriamos
traer empno y salary
Window Functions
La diferencia con las funciones de agrupacin es que siempre la window
funtion va acompaada de un OVER, el cual indica o define cual ser la
ventana (como se agrupan las filas del query).
La clusula PARTITION BY EXPRESION agrupa las filas que tienen el
mismo valor en expresin. Para cada fila del SELECT se calcula la
window function usando todas las filas que estn en el mismo grupo que
la fila corriente
Window Functions
Window functions are permitted only in the SELECT list and the
ORDER BY clause of the query. They are forbidden elsewhere, such
as in GROUP BY, HAVING and WHERE clauses. This is because
they logically execute after the processing of those clauses.
Anlisis de Consultas (3)

EXPLAIN ANALYZE select * from dh01 where tipo_sexo='M';

Vista grafica de la consulta (F7 en PgAdmin III)

EXPLAIN ANALYZE select * from dh01, dh03


where dh01.nro_legaj = dh03.nro_legaj;

- Nested Loop Join


- Merge Sort Join
- Bitmap And
- Hash Join
- Sort
Estadsticas

 PostgreSQL trae un recolector de estadsticas sobre el


uso de la base de datos.

 Las estadsticas que se recolectan se configuran en


postgresql.conf, apartado RUNTIME STATISTICS

 Muy til para tener una idea rpida y sencilla sobre lo


que sucede en cada tabla

 Ver Tablas del catalogo pg_stat_*

select pg_stat_get_tuples_updated(1530410); -- dh21_original


SIU Capacitacin Interna

ndices (10)

 Hash
 Implementacin de las dispersiones (Hashing) lineales de
Litwin
 Es el indicado cuando la clave del ndice no se repite y la
bsqueda es por un valor nico
 En diferentes foros indican que los ndices Hash son
claramente deficientes frente a B-tree (en PostgreSQL)
=

 GiST y GIN
 Son usadas en sistemas de informacin geogrfica.
 Es una forma mas generalizada de los R-Tree
ndices en Order By (8)

11.4. Indexes and ORDER BY


In addition to simply finding the rows to be returned by a query, an index may be able to deliver them in a specific
sorted order. This allows a query's ORDER BY specification to be honored without a separate sorting step. Of the
index types currently supported by PostgreSQL, only B-tree can produce sorted output the other index types
return matching rows in an unspecified, implementation-dependent order.
The planner will consider satisfying an ORDER BY specification either by scanning an available index that matches
the specification, or by scanning the table in physical order and doing an explicit sort. For a query that requires
scanning a large fraction of the table, an explicit sort is likely to be faster than using an index because it requires
less disk I/O due to following a sequential access pattern. Indexes are more useful when only a few rows need be
fetched. An important special case is ORDER BY in combination with LIMIT n: an explicit sort will have to process
all the data to identify the first n rows, but if there is an index matching the ORDER BY, the first n rows can be
retrieved directly, without scanning the remainder at all.
By default, B-tree indexes store their entries in ascending order with nulls last. This means that a forward scan of
an index on column x produces output satisfying ORDER BY x (or more verbosely, ORDER BY x ASC NULLS LAST).
The index can also be scanned backward, producing output satisfying ORDER BY x DESC (or more verbosely,
ORDER BY x DESC NULLS FIRST, since NULLS FIRST is the default for ORDER BY DESC).
You can adjust the ordering of a B-tree index by including the options ASC, DESC, NULLS FIRST, and/or NULLS LAST
when creating the index; for example:
CREATE INDEX test2_info_nulls_low ON test2 (info NULLS FIRST); CREATE INDEX test3_desc_index ON test3 (id
DESC NULLS LAST);
ndices (9)

 R-tree

 Implementacin del algoritmo de particin cuadrtica


de Guttman
 Los R-tree pueden manejar datos multidimensionales

 Ejemplo: atributo del tipo point (x,y)


Optimizacin de Consultas
Indices
Tipos de Indices
ndices (6)

CREATE [ UNIQUE ] INDEX [CONCURRENTLY] name ON table


[USING method] ({ column | ( expression )}
[WITH (storage_parameter = value [, ... ] )]
[TABLESPACE tablespace ]
[ WHERE predicate ]
 Storage Parameter Fillfactor
 Similar interpretacin al Fillfactor de las tablas
Objet Min Max
Table 10 100
Index Btree 10 90
Index Hash 10 75 Btree, fillfactor por defecto 90%
Index GiST 10 90
Index GIN 10 100
SIU Capacitacin Interna

ndices (11)

CREATE [ UNIQUE ] INDEX [CONCURRENTLY] name ON table


[USING method] ({ column | ( expression )}
[WITH (storage_parameter = value [, ... ] )]
[TABLESPACE tablespace ]
[ WHERE predicate ]

 Permite armar un ndice en una ubicacin


(tablespace) especifica.
CREATE INDEX peliculas_genero_ix ON peliculas(genero)
TABLESPACE new_tabspace;
SIU Capacitacin Interna

ndices (2)

CREATE [ UNIQUE ] INDEX [CONCURRENTLY] name ON table


[USING method] ({ column | ( expression )}
[WITH (storage_parameter = value [, ... ] )]
[TABLESPACE tablespace ]
[ WHERE predicate ]

 + Permite la actualizacin de la tabla mientras lo


crea

 - Si falla
 ndices incompletos e inutilizables.
 Puede pasar de que quede la constraint UNIQUE
Multiples ndices
given an index on (a, b) a query condition like WHERE a = 5 AND b = 6 could use the index, but a query like WHERE a = 5 OR b = 6 could
not directly use the index.
Fortunately, PostgreSQL has the ability to combine multiple indexes The system can form AND and OR conditions across several index
scans.
For example, a query like WHERE x = 42 OR x = 47 OR x = 53 OR x = 99 could be broken down into four separate scans of an index on x,
each scan using one of the query clauses. The results of these scans are then ORed together to produce the result.
Another example is that if we have separate indexes on x and y, one possible implementation of a query like WHERE x = 5 AND y = 6 is
to use each index with the appropriate query clause and then AND together the index results to identify the result rows.

To combine multiple indexes, the system scans each needed index and prepares a bitmap in memory giving the locations of table rows
that are reported as matching that index's conditions. The bitmaps are then ANDed and ORed together as needed by the query. Finally,
the actual table rows are visited and returned.
The table rows are visited in physical order, because that is how the bitmap is laid out; this means that any ordering of the original
indexes is lost, and so a separate sort step will be needed if the query has an ORDER BY clause. For this reason, and because each
additional index scan adds extra time, the planner will sometimes choose to use a simple index scan even though additional indexes are
available that could have been used as well.
In all but the simplest applications, there are various combinations of indexes that might be useful, and the database developer must
make trade-offs to decide which indexes to provide. Sometimes multicolumn indexes are best, but sometimes it's better to create
separate indexes and rely on the index-combination feature. For example, if your workload includes a mix of queries that sometimes
involve only column x, sometimes only column y, and sometimes both columns, you might choose to create two separate indexes on x
and y, relying on index combination to process the queries that use both columns. You could also create a multicolumn index on (x, y).
This index would typically be more efficient than index combination for queries involving both columns, but as discussed in Section
11.3, it would be almost useless for queries involving only y, so it should not be the only index. A combination of the multicolumn index
and a separate index on y would serve reasonably well. For queries involving only x, the multicolumn index could be used, though it
would be larger and hence slower than an index on x alone. The last alternative is to create all three indexes, but this is probably only
reasonable if the table is searched much more often than it is updated and all three types of query are common. If one of the types of
query is much less common than the others, you'd probably settle for creating just the two indexes that best match the common types.
Esquemas de las tablas del ejemplo

Anda mungkin juga menyukai