Bases de Datos
Geométricas
El punto central no es dibujar figuras. Es conseguir que una base de datos pueda guardar, comparar, medir, buscar y relacionar objetos geométricos de forma eficiente.
Si es tu primera vez: seguí el orden del índice. Está armado para ir de la idea → la geometría → la consulta → el índice.
La base no guarda “un dibujito”. Guarda objetos matemáticos con operadores propios.
Todo el tema
en seis pasos
Si entendés esta cadena, después los operadores dejan de parecer una sopa de símbolos.
BD geométrica = base relacional + objetos geométricos + operadores espaciales + consultas geométricas + índices multidimensionales.
¿Qué es una base
de datos geométrica?
Es una base capaz de tratar objetos geométricos como verdaderos tipos de datos y no solamente como números X e Y sueltos.
Guardar coordenadas sueltas
x1 = 2
y1 = 1
x2 = 9
y2 = 6
La base ve números.
Tipo geométrico
BOX
((9,6),(2,1))
La base sabe que es una región rectangular.
¿Está adentro?
Consulta de contención.
¿Se cruzan?
Consulta de intersección.
¿Cuál está más cerca?
Consulta de distancia.
Geométrica
≠ geográfica
Espacio abstracto
Puede trabajar simplemente sobre un plano cartesiano X/Y.
Superficie terrestre
Se preocupa por referencias geográficas, proyecciones, sistemas de coordenadas, Tierra curva, etc.
GPS · WGS84 · EPSG · latitud · longitud · proyecciones cartográficas.
Ejemplo
Si un robot está en:
POINT(25, 10)
puede significar simplemente:
10 metros sobre el eje Y
dentro de un galpón.
Dos vocabularios
que podés encontrarte
Hay más de una forma de modelar geometría dentro de una base de datos. Conviene reconocer ambas.
7 tipos propios
Vienen incluidos directamente en PostgreSQL.
Geometry
Es otro modelo geométrico, muy usado por extensiones y otros motores.
El tipo
geometry
también puede representar formas
en un plano cartesiano.
PostgreSQL nativo
lseg '[(0,0),(5,5)]'
OGC / PostGIS
LINESTRING(0 0, 5 5)
Esta guía se concentra primero en PostgreSQL nativo. La sección OGC está para que, si aparece en clase, no pienses que es otro tema totalmente distinto.
El plano cartesiano
Los tipos geométricos nativos de PostgreSQL representan objetos espaciales bidimensionales.
X
Coordenada horizontal.
Y
Coordenada vertical.
Crear un punto
SELECT point '(4,3)';
-- (4,3)
El significado de la unidad lo define el modelo de tu aplicación.
Acceder a X e Y
SELECT posicion[0] AS x,
posicion[1] AS y
FROM sensores;
PostgreSQL permite tratar
point
como un arreglo de dos componentes:
Dimensión, borde
e interior
Antes de memorizar nombres, sirve entender qué ocupa realmente cada objeto.
Punto
Tiene posición, pero no longitud ni área.
Objetos lineales
Segmentos, rectas y caminos poseen longitud.
Regiones
Polygon, box y circle delimitan superficies.
Los 7 tipos
geométricos nativos
| Tipo | Representa | Sintaxis | Almacenamiento |
|---|---|---|---|
| point | Punto | (x,y) | 16 bytes |
| line | Recta infinita | {A,B,C} | 24 bytes |
| lseg | Segmento finito | [(x1,y1),(x2,y2)] | 32 bytes |
| box | Rectángulo | (x1,y1),(x2,y2) | 32 bytes |
| path | Camino abierto/cerrado | [...] o (...) | 16 + 16n bytes |
| polygon | Región poligonal | ((x1,y1),...) | 40 + 16n bytes |
| circle | Círculo | <(x,y),r> | 24 bytes |
POINT
El objeto más simple: una única posición dentro del plano.
SELECT point '(3,5)';
-- (3,5)
X = 3
Y = 5
0D
No tiene área.
Crear desde números
SELECT point(23.4, -44.5);
Uso típico
Sensores, robots, posiciones, nodos, centros, ubicaciones de objetos, puntos de control.
LINE vs LSEG
LINE
Representa una recta que continúa infinitamente hacia ambos lados.
SELECT line(
point '(0,0)',
point '(4,4)'
);
Internamente se representa como:
A·x + B·y + C = 0
LSEG
Representa un segmento entre dos extremos.
SELECT lseg '[(0,0),(4,4)]';
LINE
Infinita.
LSEG
Finito.
LINE ≠ LSEG
BOX
Un rectángulo alineado con los ejes X e Y.
SELECT box '((6,5),(1,1))';
Solamente hacen falta dos esquinas opuestas.
width()
ancho
height()
alto
center()
centro
area()
superficie
SELECT
width(box '((6,5),(1,1))'),
height(box '((6,5),(1,1))'),
area(box '((6,5),(1,1))');
PATH
Una secuencia ordenada de puntos conectados.
[ ]
path '[
(0,0),
(2,3),
(5,1)
]'
Los extremos no se conectan.
( )
path '(
(0,0),
(2,3),
(5,1)
)'
El recorrido vuelve al inicio.
Funciones útiles
SELECT
isopen(mi_path),
isclosed(mi_path),
npoints(mi_path),
length(mi_path);
Abrir o cerrar
SELECT pclose(
path '[(0,0),(1,1),(2,0)]'
);
SELECT popen(
path '((0,0),(1,1),(2,0))'
);
POLYGON
Una región definida por una lista de vértices.
SELECT polygon '(
(0,0),
(6,0),
(5,4),
(2,6),
(0,3)
)';
Recorrido
Describe el camino formado por sus segmentos.
Región
Incluye el área contenida por el borde.
Número de vértices
SELECT npoints(
polygon '((0,0),(4,0),(2,3))'
);
-- 3
CIRCLE
centro
radio
región circular
SELECT circle '<(5,5),3>';
center()
centro
radius()
radio
diameter()
diámetro
SELECT
center(circle '<(5,5),3>'),
radius(circle '<(5,5),3>'),
diameter(circle '<(5,5),3>');
No memorices símbolos.
Primero entendé la pregunta.
Podemos agrupar las relaciones según qué queremos saber.
¿Cómo se relacionan?
contiene
está dentro
se intersecta
se solapa
¿Qué tan lejos?
distancia
punto más cercano
vecinos
¿Dónde está?
izquierda
derecha
arriba
abajo
¿Cómo está orientado?
horizontal
vertical
paralelo
perpendicular
problema → familia de relación → operador → SQL
Contención
y solapamiento
@> / <@
El polígono contiene al punto.
polygon @> point
point <@ polygon
| Operador | Significado | Ejemplo |
|---|---|---|
| @> | A contiene B | circle contiene point |
| <@ | A está contenido en o sobre B | point dentro de polygon |
| && | A y B se solapan | dos boxes comparten espacio |
| ~= | misma geometría | dos puntos iguales |
SELECT
circle '<(0,0),2>'
@>
point '(1,1)';
-- true
&&
no significa “son iguales”.
Significa que comparten al menos algún espacio/punto para los tipos compatibles.
Dos preguntas distintas
?#
¿Los objetos se intersectan?
#
¿Cuál es el punto o región de intersección?
¿Se cruzan?
SELECT
lseg '[(0,0),(4,4)]'
?#
lseg '[(0,4),(4,0)]';
-- true
¿Dónde?
SELECT
lseg '[(0,0),(4,4)]'
#
lseg '[(0,4),(4,0)]';
-- (2,2)
#
entre dos
BOX:
el resultado puede ser
la región rectangular común.
Izquierda, derecha,
horizontal, paralelo...
| Operador | Pregunta |
|---|---|
| << | ¿A está estrictamente a la izquierda de B? |
| >> | ¿A está estrictamente a la derecha de B? |
| <<| | ¿A está estrictamente debajo de B? |
| |>> | ¿A está estrictamente arriba de B? |
| &< | A no se extiende a la derecha de B |
| &> | A no se extiende a la izquierda de B |
| &<| | A no se extiende por encima de B |
| |&> | A no se extiende por debajo de B |
| Operador | Significado |
|---|---|
| ?- | horizontal / dos puntos horizontalmente alineados |
| ?| | vertical / dos puntos verticalmente alineados |
| ?|| | paralelos |
| ?-| | perpendiculares |
Paralelos
SELECT
lseg '[(0,0),(5,0)]'
?||
lseg '[(0,3),(5,3)]';
-- true
Perpendiculares
SELECT
lseg '[(0,0),(0,5)]'
?-|
lseg '[(0,0),(5,0)]';
-- true
Distancia
y punto más cercano
<->
Devuelve una distancia.
##
Devuelve un punto del segundo objeto.
ORDER BY
Ordena por cercanía.
Distancia entre dos puntos
SELECT
point '(0,0)'
<->
point '(3,4)';
-- 5
√[(3 − 0)² + (4 − 0)²]
= √25
= 5
Punto más cercano sobre otro objeto
SELECT
point '(0,0)'
##
lseg '[(2,0),(0,2)]';
-- (1,1)
<->
→ ¿cuánto?
##
→ ¿en qué punto?
Las preguntas
que se repiten siempre
Esta clasificación es más útil que aprender veinte operadores aislados.
¿Dónde cae este punto?
Encontrar la región que contiene un punto.
punto <@ region
¿Qué hay en esta zona?
Recuperar objetos dentro de una ventana.
posicion <@ ventana
¿Qué se cruza?
Encontrar objetos que intersectan otro.
objeto ?# consulta
¿Qué está más cerca?
Buscar objetos con distancia mínima.
ORDER BY
posicion <-> consulta
LIMIT k
¿Qué pares se relacionan?
Relacionar dos tablas mediante geometría.
JOIN zonas z
ON p.posicion <@ z.area
Consulta espacial
No es “mostrar un mapa”. Es ejecutar una condición sobre conjuntos de geometrías.
Medir e inspeccionar
una geometría
| Operación | Sirve para | Tipos principales |
|---|---|---|
| area() | área | box, path cerrado, circle |
| center() | centro | box, circle |
| length() | longitud total | lseg, path |
| width() | ancho | box |
| height() | alto | box |
| radius() | radio | circle |
| diameter() | diámetro | circle |
| npoints() | cantidad de puntos | path, polygon |
| isopen() | ¿path abierto? | path |
| isclosed() | ¿path cerrado? | path |
| slope() | pendiente entre puntos | point + point |
| diagonal() | diagonal | box → lseg |
PostgreSQL también tiene operadores unarios
@-@
Longitud total.
@-@ lseg
@-@ path
@@
Punto central.
@@ box
@@ lseg
@@ polygon
@@ circle
#
Cantidad de puntos si se usa como operador unario.
# path
# polygon
Trasladar, escalar
y rotar
Traslación
Traslación inversa
Escala / rotación
Escala / rotación
Trasladar
SELECT
point '(2,3)'
+
point '(5,1)';
-- (7,4)
posición inicial
desplazamiento
resultado
Escalar un path
SELECT
path '((0,0),(1,0),(1,1))'
*
point '(3,0)';
-- ((0,0),(3,0),(3,3))
* y /,
PostgreSQL interpreta el point
de manera equivalente a un número complejo.
Eso permite combinar escala y rotación.
Para una primera clase, alcanza con entender la idea.
Construir un objeto
a partir de otro
Dos puntos → LINE
SELECT line(
point '(0,0)',
point '(4,4)'
);
Dos puntos → LSEG
SELECT lseg(
point '(0,0)',
point '(4,4)'
);
BOX → centro
SELECT point(
box '((6,4),(0,0))'
);
-- (3,2)
POLYGON → BOX
SELECT box(
polygon '(
(0,0),
(5,1),
(3,6)
)'
);
Polygon → Path
SELECT path(
polygon '((0,0),(4,0),(2,3))'
);
Circle → Polygon aproximado
SELECT polygon(
8,
circle '<(0,0),5>'
);
El círculo se aproxima mediante un polígono de 8 vértices.
polygon(circle)
que genera por defecto una aproximación de 12 puntos.
Guardar geometrías
en tablas reales
CREATE TABLE robots (
id SERIAL PRIMARY KEY,
nombre VARCHAR(80),
posicion POINT,
trayectoria PATH,
zona_seguridad CIRCLE
);
Insertar
INSERT INTO robots
(
nombre,
posicion,
trayectoria,
zona_seguridad
)
VALUES
(
'Robot A',
point '(4,3)',
path '[(4,3),(6,4),(8,4)]',
circle '<(4,3),2>'
);
Consultar
SELECT
nombre,
posicion
FROM robots
WHERE
posicion
<@
box '((10,10),(0,0))';
SELECT · FROM · WHERE · JOIN · ORDER BY · LIMIT
Lo nuevo es que el dato y la condición son geométricos.
Spatial Join
Dos tablas pueden relacionarse porque sus geometrías cumplen una condición espacial.
JOIN normal
SELECT *
FROM robots r
JOIN sectores s
ON r.sector_id = s.id;
La relación se basa en IDs.
JOIN geométrico
SELECT
r.nombre AS robot,
s.nombre AS sector
FROM robots r
JOIN sectores s
ON
r.posicion
<@
s.area;
valor = valor
geometría ↔ geometría
Un galpón robotizado
Este ejemplo junta casi todo sin utilizar información geográfica.
POINT
posición
PATH
recorrido
POLYGON
región
Modelo
CREATE TABLE robots (
id SERIAL PRIMARY KEY,
nombre TEXT,
posicion POINT,
recorrido PATH,
radio_seguridad CIRCLE
);
CREATE TABLE sectores (
id SERIAL PRIMARY KEY,
nombre TEXT,
area POLYGON
);
SELECT
r.nombre,
s.nombre
FROM robots r
JOIN sectores s
ON
r.posicion
<@
s.area;
SELECT
nombre,
posicion <-> point '(50,30)' AS distancia
FROM robots
ORDER BY
posicion <-> point '(50,30)'
LIMIT 1;
SELECT
a.nombre,
b.nombre
FROM robots a
JOIN robots b
ON a.id < b.id
WHERE
a.radio_seguridad
&&
b.radio_seguridad;
SELECT nombre
FROM robots
WHERE
posicion
<@
box '((60,40),(20,10))';
¿Por qué un B-tree
no resuelve todo esto?
Orden natural
1
4
8
15
29
51
Es sencillo hablar de menor y mayor.
Varias dimensiones
Un objeto puede tener:
“¿qué hay dentro?”
“¿qué se solapa?”
“¿qué queda más cerca?”
Bounding Box / MBR
Comparar una forma compleja puede ser caro. Comparar un rectángulo que la envuelve suele ser mucho más barato.
forma real + rectángulo envolvente
Rectángulo mínimo, normalmente alineado a los ejes, que encierra una geometría.
Filter + Refine
Usar una representación barata para descartar regiones imposibles.
Queda un conjunto mucho más pequeño.
Verificar la condición exacta si hace falta.
GiST
GiST significa Generalized Search Tree.
Framework
No es una única estructura rígida.
Índices especializados
Permite implementar estrategias apropiadas para dominios complejos.
“GiST = R-tree”
Es más correcto pensar:
GiST es un framework sobre el que pueden implementarse distintas estrategias de búsqueda, incluidas ideas tipo R-tree.
Crear índice
CREATE INDEX robots_pos_gist
ON robots
USING GIST (posicion);
¿Qué gana la base?
Puede usar el índice para evitar revisar todas las filas en determinadas consultas compatibles.
SP-GiST
Space-Partitioned GiST: familias de árboles que dividen repetidamente el espacio.
Quadtree
Divide un espacio 2D en cuatro regiones.
k-d tree
Divide el espacio según distintas dimensiones.
point,
PostgreSQL ofrece:
quad_point_ops → enfoque quadtree
kd_point_ops → enfoque k-d tree.
CREATE INDEX robots_pos_spgist
ON robots
USING SPGIST (posicion);
GiST = framework generalizado.
SP-GiST = estructuras basadas en particionar el espacio.
KNN
K Nearest Neighbours: encontrar los K objetos más cercanos.
SELECT
nombre,
posicion <-> point '(10,10)' AS distancia
FROM robots
ORDER BY
posicion <-> point '(10,10)'
LIMIT 5;
(10,10)
<->
menor → mayor
cinco vecinos
<->.
No todo se indexa
de la misma forma
| Tipo | GiST nativo | SP-GiST nativo |
|---|---|---|
| point | ✓ point_ops | ✓ quad / kd |
| box | ✓ box_ops | ✓ box_ops |
| polygon | ✓ poly_ops | ✓ poly_ops |
| circle | ✓ circle_ops | — nativo |
| line | — clase geométrica nativa específica | — |
| lseg | — clase geométrica nativa específica | — |
| path | — clase geométrica nativa específica | — |
Lo importante es: tipo de dato + operador + clase de índice deben ser compatibles.
EXPLAIN
Crear un índice no alcanza. Hay que ver si PostgreSQL realmente decide utilizarlo.
EXPLAIN
SELECT nombre
FROM robots
ORDER BY
posicion <-> point '(10,10)'
LIMIT 5;
Más detalle
EXPLAIN
(
ANALYZE,
BUFFERS
)
SELECT nombre
FROM robots
ORDER BY
posicion <-> point '(10,10)'
LIMIT 5;
Plan estimado
Muestra cómo piensa ejecutar la consulta.
Ejecución real
Ejecuta la consulta y muestra métricas reales.
EXPLAIN ANALYZE
realmente ejecuta
la consulta.
En consultas que modifican datos, eso importa muchísimo.
Trampas comunes
= no siempre significa misma geometría
Algunos operadores escalares comparan áreas.
Para la noción habitual de igualdad geométrica:
~=
PATH cerrado ≠ POLYGON
Path describe el recorrido. Polygon incluye la región interior.
area(path)
Un path abierto devuelve NULL.
Si se autointersecta, el área puede no ser útil.
LINE ≠ LSEG
Una línea es infinita. Un segmento tiene extremos.
Rotar BOX
Sigue tratándose como una caja alineada a los ejes.
double precision
Las coordenadas son números flotantes.
No tienen precisión matemática infinita.
GiST ≠ R-tree
GiST es un framework generalizado de indexación.
Índice ≠ magia
El optimizador decide si conviene usarlo.
¿Qué creo que
pudieron haber visto?
Hasta que aparezca el PDF esto sigue siendo una estimación, pero ahora está mucho mejor acotada.
Datos geométricos
Qué son y para qué sirven.
POINT
Coordenadas X/Y.
7 tipos
point, line, lseg, box, path, polygon, circle.
Sintaxis
Cómo escribir cada tipo.
Operadores
contención, posición, distancia...
Funciones
area, center, length, radius...
Intersecciones
?# y #
Índices
GiST o idea de indexación espacial.
SP-GiST / KNN
Más probable si profundizaron rendimiento.
Lo que aprendería sí o sí hoy
1. Concepto
2. Tipos
3. Relaciones
4. SQL
5. Índices
No arrancaría por GiST si todavía confundís LINE con LSEG.
Flashcards
Intentá responder antes de hacer clic.
¿Geométrica y geográfica son lo mismo?
clicNo
Una BD geométrica puede trabajar simplemente en un plano abstracto X/Y.
LINE vs LSEG
clicDiferencia
LINE es infinita. LSEG tiene dos extremos.
PATH cerrado vs POLYGON
clicSemántica
PATH = recorrido. POLYGON = región con interior.
¿Qué hace @>?
clicContiene
Pregunta si el primer objeto contiene al segundo.
¿Qué hace <->?
clicDistancia
Devuelve distancia entre tipos compatibles.
¿Qué es KNN?
clicK vecinos cercanos
Encontrar los K objetos más cercanos a una consulta.
¿GiST = R-tree?
clicNo exactamente
GiST es un framework generalizado sobre el que pueden implementarse distintos esquemas.
¿Qué es un quadtree?
clicPartición espacial
Divide repetidamente una región 2D en cuatro partes.
¿Qué es Point Location?
clicUbicar un punto
Determinar qué región contiene una posición dada.
Glosario
Quiz
Hacelo sin volver arriba.
Si entendés esto,
entendiste el núcleo
01 · Representación
Una geometría puede almacenarse como tipo de dato.
02 · Tipos
PostgreSQL incluye: point, line, lseg, box, path, polygon y circle.
03 · Semántica
LINE no es LSEG. PATH cerrado no es POLYGON.
04 · Relaciones
Contención, intersección, dirección, orientación y distancia.
05 · Consultas
Point location, range query, intersection, KNN y spatial join.
06 · SQL
SQL normal + condiciones geométricas.
07 · Índices
GiST y SP-GiST permiten búsquedas multidimensionales.
08 · Rendimiento
No alcanza con guardar geometrías: hay que poder encontrarlas eficientemente.
Si tengo miles o millones de objetos geométricos:
¿cómo los represento, almaceno y consulto eficientemente según su posición, forma, relación y distancia?
Geometría computacional
A partir de acá, la pregunta deja de ser solamente “¿qué operador SQL uso?” y pasa a ser: “¿qué algoritmo o estructura resuelve mejor esta consulta?”
Range Searching
Encontrar objetos dentro de una región.
Point Location
Encontrar la región que contiene un punto.
Nearest Neighbour
Encontrar objetos próximos.
Voronoi
Dividir el espacio según proximidad a distintos sitios.
Delaunay
Triangulación relacionada con Voronoi.
Sweep Line
Técnica para resolver problemas de intersección de manera eficiente.
Antes dominá:
tipos → relaciones → consultas → índices.
Para seguir estudiando
Si después querés comprobar, ampliar o practicar algo, iría primero a documentación oficial.
Geometric Types
Los siete tipos, representación y sintaxis.
Geometric Functions and Operators
Operadores, funciones y conversiones.
GiST
Framework de índices y operator classes.
SP-GiST
Quadtrees, k-d trees y partición espacial.
Geometry Model
Para entender el segundo vocabulario: Point, LineString, Polygon, Multi...
PostgreSQL · Geometría 2D · SQL · GiST · SP-GiST