CTEs y Queries Recursivas
Álvaro Hernández Tortosa <aht@Nosys.es>
Acerca de mí
●
●
●

●
●

Álvaro Hernández Tortosa <aht@Nosys.es>
Fundador y Director Técnico en NOSYS
¿Qué hacemos en NOSY...
Common Table Expression (CTE)
Son como VIEWS temporales, con nombre, que se pueden
crear al vuelo para simplificar la escr...
WITH en 1 slide
Sin CTEs
SELECT cols FROM tabla1
INNER JOIN (SELECT cols
FROM tabla 2) AS tabla2
ON (…)
JOIN (SELECT cols
...
Sintaxis
WITH [ RECURSIVE ] with_query_name [ (
column_name [, …]
) ] AS (
select | values | insert | update | delete
)
[,...
Ejemplos
WITH tabla AS (SELECT 1) SELECT * FROM tabla;

WITH tabla (i) AS (SELECT 1) SELECT i FROM tabla;

WITH seq (i) AS...
Ejemplos (II)
WITH regional_sales AS (
SELECT region, SUM(amount) AS total_sales
FROM orders GROUP BY region
), top_region...
Ejemplos (III): WITH con mutación de datos
-- Obtener las filas actualizadas
WITH t AS (
UPDATE products SET price = price...
Estructuras auto-referenciadas en RDBMSs
Los grafos, árboles y estructuras recursivas son difíciles de
representar en RDBM...
Ejemplo: para cada red, saber el “path” completo
CREATE TABLE ip_network (
mask
cidr
PRIMARY KEY,
name
varchar
,
parent_ne...
Procesado a nivel de aplicación
Solución a nivel de BBDD: queries recursivas
Sintaxis:
WITH RECURSIVE nombre AS (
-- valor inicial
SELECT cols FROM tabla
...
Recordatorio: UNION vs. UNION ALL
aht=> SELECT * FROM generate_series(1,2) UNION SELECT * FROM
generate_series(1,2) ORDER ...
Ejemplos
WITH RECURSIVE t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 100
) SELECT sum(n) FROM t;
WITH RECURS...
Resolviendo el “path completo” en redes IP
WITH RECURSIVE ip_network_recursive (mask, mask_path, name,
parent_network, is_...
Resolviendo el “path completo” en redes IP (II)
name

|

mask_path

--------------------------+---------------------------...
El caso de Disqus
Disqus, la plataforma para “outsourcing” de comentarios
en una web
●

Los comentarios son de naturaleza ...
Alternativa para árboles: la extensión ltree
●

Extensión (CREATE EXTENSION ltree) para árboles

Usa paths materializados ...
Más información

●

http://www.postgresql.org/docs/9.3/static/queries-with.html

●

http://wiki.postgresql.org/wiki/CTERea...
CTEs y Queries Recursivas
Álvaro Hernández Tortosa <aht@Nosys.es>
Upcoming SlideShare
Loading in...5
×

CTEs y Queries Recursivas

983

Published on

Charla impartida en el Grupo de PostgreSQL España (meetup.com/PostgreSQL-Espana/) de diciembre (http://www.meetup.com/PostgreSQL-Espana/events/155241452/).

En esta presentación de PostgreSQL se describen las CTEs o Common Table Expressions, disponibles desde la versión 8.4, que permiten simplificar la escritura de consultas con vistas "dinámicas", que no necesitan ser definidas previamente y que pueden referenciarse entre sí. También introduce soporte de queries recursivas, que permiten resolver de manera muy eficiente en la base de datos problemas con estructuras de datos de tipo autoreferenciadas, entre otros. Se muestra un caso como el de Disqus donde la velocidad de query se multiplicó por 5 con el uso de queries recursivas en los comentarios.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
983
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
23
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

CTEs y Queries Recursivas

  1. 1. CTEs y Queries Recursivas Álvaro Hernández Tortosa <aht@Nosys.es>
  2. 2. Acerca de mí ● ● ● ● ● Álvaro Hernández Tortosa <aht@Nosys.es> Fundador y Director Técnico en NOSYS ¿Qué hacemos en NOSYS? ✔ Formación, consultoría y desarrollo de software con PostgreSQL (y Java) ✔ Partners de EnterpriseDB ✔ Formación avanzada en Java con Javaspecialists.eu: Java Master Course y Java Concurrency Course ✔ Partners de Amazon AWS. Formación y consultoría en AWS Twitter: @ahachete LinkedIn: http://es.linkedin.com/in/alvarohernandeztortosa/
  3. 3. Common Table Expression (CTE) Son como VIEWS temporales, con nombre, que se pueden crear al vuelo para simplificar la escritura de consultas ● ● ● Se utilizan con la cláusula WITH: ✔ puede haber tantas “vistas temporales” como se quiera ✔ se pueden hacer JOINs entre ellas y referenciar entre ellas también ✔ incluso a sí mismas, para dar lugar a la recursividad Disponibles desde PostgreSQL 8.4 (escribibles desde 9.1)
  4. 4. WITH en 1 slide Sin CTEs SELECT cols FROM tabla1 INNER JOIN (SELECT cols FROM tabla 2) AS tabla2 ON (…) JOIN (SELECT cols FROM tabla 3) AS tabla3 ON (…) WHERE … CTEs (WITH) WITH tabla2 AS ( SELECT cols FROM tabla2 ), tabla3 AS ( SELECT cols FROM tabla3 ) SELECT cols FROM tabla1 INNER JOIN tabla2 ON (…) l JOIN tabla3 ON (…) WHERE …
  5. 5. Sintaxis WITH [ RECURSIVE ] with_query_name [ ( column_name [, …] ) ] AS ( select | values | insert | update | delete ) [, …] SELECT … with_query_name …
  6. 6. Ejemplos WITH tabla AS (SELECT 1) SELECT * FROM tabla; WITH tabla (i) AS (SELECT 1) SELECT i FROM tabla; WITH seq (i) AS ( SELECT generate_series(1,10) ), seq2 (i) AS ( SELECT * FROM seq WHERE i%2=0 ) SELECT i FROM seq2 RIGHT OUTER JOIN seq ON (seq.i = seq2.i);
  7. 7. Ejemplos (II) WITH regional_sales AS ( SELECT region, SUM(amount) AS total_sales FROM orders GROUP BY region ), top_regions AS ( SELECT region FROM regional_sales WHERE tot_sales > ( SELECT SUM(tot_sales)/10 FROM regional_sales ) ) SELECT region, product, SUM(quantity) AS product_units, SUM(amount) AS product_sales FROM orders WHERE region IN (SELECT region FROM top_regions) GROUP BY region, product; http://www.postgresql.org/docs/9.3/static/queries-with.html
  8. 8. Ejemplos (III): WITH con mutación de datos -- Obtener las filas actualizadas WITH t AS ( UPDATE products SET price = price * 1.05 RETURNING * ) SELECT * FROM t; -- cuidado: “FROM t”, no “FROM products” -- Realizar varias operaciones al tiempo WITH moved_rows AS ( DELETE FROM products WHERE "date" >= '2010-10-01' AND "date" < '2010-11-01' RETURNING * ) INSERT INTO products_log SELECT * FROM moved_rows; http://www.postgresql.org/docs/9.3/static/queries-with.html
  9. 9. Estructuras auto-referenciadas en RDBMSs Los grafos, árboles y estructuras recursivas son difíciles de representar en RDBMSs ● La solución “típica” es una tabla auto-referenciada, donde la FK apunta a la propia tabla ● El problema es: ¿cómo realizar una consulta que deba recorrer el árbol, el grafo, o recursivamente la tabla? ● Y la solución naive es con lenguajes procedurales, pero ¿puede hacerse de otra manera? ●
  10. 10. Ejemplo: para cada red, saber el “path” completo CREATE TABLE ip_network ( mask cidr PRIMARY KEY, name varchar , parent_network cidr REFERENCES ip_network (mask), CONSTRAINT network_contained_in_parent_network CHECK ( parent_network IS NULL OR mask << parent_network ) ); SELECT * FROM ip_network ORDER BY random() LIMIT 3; mask | name | parent_network --------------+------------+---------------10.0.32.0/19 | Storage | 10.0.0.0/16 10.0.17.0/24 | S.S. Reyes | 10.0.16.0/20 10.0.16.0/28 | dom0 | 10.0.16.0/24
  11. 11. Procesado a nivel de aplicación
  12. 12. Solución a nivel de BBDD: queries recursivas Sintaxis: WITH RECURSIVE nombre AS ( -- valor inicial SELECT cols FROM tabla UNION ALL -- o UNION -- elemento recursivo: se apunta a sí mismo SELECT cols FROM nombre -- condición de terminación WHERE … ) SELECT * FROM nombre;
  13. 13. Recordatorio: UNION vs. UNION ALL aht=> SELECT * FROM generate_series(1,2) UNION SELECT * FROM generate_series(1,2) ORDER BY 1 ASC; generate_series ----------------1 2 aht=> SELECT * FROM generate_series(1,2) UNION ALL SELECT * FROM generate_series(1,2) ORDER BY 1 ASC; generate_series ----------------1 1 2 2
  14. 14. Ejemplos WITH RECURSIVE t(n) AS ( VALUES (1) UNION ALL SELECT n+1 FROM t WHERE n < 100 ) SELECT sum(n) FROM t; WITH RECURSIVE subdepartment AS ( SELECT * FROM department WHERE name = 'A' UNION ALL SELECT d.* FROM department AS d JOIN subdepartment AS sd ON (d.parent_department = sd.id) ) SELECT * FROM subdepartment ORDER BY name; http://www.postgresql.org/docs/9.3/static/queries-with.html http://wiki.postgresql.org/wiki/CTEReadme
  15. 15. Resolviendo el “path completo” en redes IP WITH RECURSIVE ip_network_recursive (mask, mask_path, name, parent_network, is_leaf) AS ( SELECT mask, abbrev(mask), name, parent_network, parent_network IS NULL FROM noc.ip_network UNION SELECT i1.mask, abbrev(i2.mask) || ' > ' || i1.mask_path, i1.name, i2.parent_network, i2.parent_network IS NULL FROM ip_network_recursive AS i1 INNER JOIN noc.ip_network AS i2 ON (i1.parent_network = i2.mask) ) SELECT name, mask, mask_path FROM ip_network_recursive WHERE is_leaf;
  16. 16. Resolviendo el “path completo” en redes IP (II) name | mask_path --------------------------+---------------------------------------------------NOSYS - private | 10.0/16 NOSYS - public | 62.93.188.160/27 NOSYS - private - legacy | 192.168.5/24 Service | 10.0/16 > 10.0.16/20 Storage | 10.0/16 > 10.0.32/19 Out of band management | 10.0/16 > 10.0.64/20 Reserved | 10.0/16 > 10.0.0/20 Easynet datacenter | 10.0/16 > 10.0.16/20 > 10.0.16/24 Easynet datacenter | 10.0/16 > 10.0.64/20 > 10.0.64/24 S.S. Reyes | 10.0/16 > 10.0.16/20 > 10.0.17/24 S.S. Reyes | 10.0/16 > 10.0.64/20 > 10.0.65/24 dom0 | 10.0/16 > 10.0.16/20 > 10.0.16/24 > 10.0.16.0/28 domu - core services | 10.0/16 > 10.0.16/20 > 10.0.16/24 > 10.0.16.16/28 domu | 10.0/16 > 10.0.16/20 > 10.0.16/24 > 10.0.16.32/27 domu | 10.0/16 > 10.0.16/20 > 10.0.16/24 > 10.0.16.64/26 domu | 10.0/16 > 10.0.16/20 > 10.0.16/24 > 10.0.16.128/25
  17. 17. El caso de Disqus Disqus, la plataforma para “outsourcing” de comentarios en una web ● Los comentarios son de naturaleza jerárquica (aka recursiva) ● Migraron de MySQL con procesado de la jerarquía en la aplicación a PostgreSQL con soporte de queries recursivas. Resultados: ✔ 5x mejora velocidad ejecución de consultas ✔ 20x mejora latencia global sirviendo comentarios ●
  18. 18. Alternativa para árboles: la extensión ltree ● Extensión (CREATE EXTENSION ltree) para árboles Usa paths materializados por lo que puede ser más eficiente que CTEs ● ● Tiene índices y operadores “built-in” INSERT INTO comments (user_id, path) INSERT INTO comments (user_id, path) '0001.0002'), (7, '0001.0004'), (18, SELECT * FROM comments WHERE path <@ VALUES (1, '0001'); VALUES (6, '0001.0004.0005'); '0001.0002'; http://www.postgresql.org/docs/9.3/static/ltree.html
  19. 19. Más información ● http://www.postgresql.org/docs/9.3/static/queries-with.html ● http://wiki.postgresql.org/wiki/CTEReadme ● http://momjian.us/main/writings/pgsql/cte.pdf ● http://pgexercises.com/questions/recursive/
  20. 20. CTEs y Queries Recursivas Álvaro Hernández Tortosa <aht@Nosys.es>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×