F.10. cube — un tipo de datos para cubos multidimensionales #

F.10.1. Sintaxis
F.10.2. Precisión
F.10.3. Uso
F.10.4. Valores por defecto
F.10.5. Notas
F.10.6. Créditos

Este módulo implementa un tipo de datos cube para representar cubos multidimensionales.

Este módulo se considera trusted (confiable), es decir, puede ser instalado por usuarios no superusuarios que tengan el privilegio CREATE en la base de datos actual.

F.10.1. Sintaxis #

La Table F.1 muestra las representaciones externas válidas para el tipo cube. x, y, etc., denotan números de punto flotante.

Table F.1. Representaciones externas de cube

Sintaxis externaSignificado
xUn punto unidimensional (o un intervalo unidimensional de longitud cero)
(x)Igual que arriba
x1,x2,...,xnUn punto en el espacio n-dimensional, representado internamente como un cubo de volumen cero
(x1,x2,...,xn)Igual que arriba
(x),(y)Un intervalo unidimensional que comienza en x y termina en y o viceversa; el orden no importa
[(x),(y)]Igual que arriba
(x1,...,xn),(y1,...,yn)Un cubo n-dimensional representado por un par de sus esquinas diagonalmente opuestas
[(x1,...,xn),(y1,...,yn)]Igual que arriba

No importa en qué orden se ingresen las esquinas opuestas de un cubo. Las funciones de cube intercambian automáticamente los valores si es necesario para crear una representación interna uniforme de inferior izquierda — superior derecha. Cuando las esquinas coinciden, cube almacena solo una esquina junto con una bandera is point (es punto) para evitar desperdiciar espacio.

Los espacios en blanco se ignoran en la entrada, por lo que [(x),(y)] es lo mismo que [ ( x ), ( y ) ].

F.10.2. Precisión #

Los valores se almacenan internamente como números de punto flotante de 64 bits. Esto significa que los números con más de aproximadamente 16 dígitos significativos serán truncados.

F.10.3. Uso #

La Table F.2 muestra los operadores especializados proporcionados para el tipo cube.

Table F.2. Operadores de cube

Operador

Descripción

cube && cubeboolean

¿Se superponen los cubos?

cube @> cubeboolean

¿Contiene el primer cubo al segundo?

cube <@ cubeboolean

¿Está el primer cubo contenido en el segundo?

cube -> integerfloat8

Extrae la n-ésima coordenada del cubo (contando desde 1).

cube ~> integerfloat8

Extrae la n-ésima coordenada del cubo, contando de la siguiente manera: n = 2 * k - 1 significa el límite inferior de la k-ésima dimensión, n = 2 * k significa el límite superior de la k-ésima dimensión. Un valor negativo de n denota el valor inverso de la coordenada positiva correspondiente. Este operador está diseñado para el soporte de KNN-GiST.

cube <-> cubefloat8

Calcula la distancia euclidiana entre los dos cubos.

cube <#> cubefloat8

Calcula la distancia de Manhattan (métrica L-1) entre los dos cubos.

cube <=> cubefloat8

Calcula la distancia de Chebyshev (métrica L-inf) entre los dos cubos.


Además de los operadores anteriores, los operadores de comparación habituales mostrados en la Table 9.1 están disponibles para el tipo cube. Estos operadores comparan primero las primeras coordenadas, y si son iguales, comparan las segundas coordenadas, etc. Existen principalmente para dar soporte a la clase de operadores de índice b-tree para cube, lo que puede ser útil, por ejemplo, si quieres una restricción UNIQUE en una columna de tipo cube. De lo contrario, este ordenamiento no tiene mucha utilidad práctica.

El módulo cube también proporciona una clase de operadores de índice GiST para valores de tipo cube. Se puede utilizar un índice GiST de cube para buscar valores utilizando los operadores =, &&, @> y <@ en cláusulas WHERE.

Además, se puede utilizar un índice GiST de cube para buscar los vecinos más cercanos utilizando los operadores métricos <->, <#> y <=> en cláusulas ORDER BY. Por ejemplo, el vecino más cercano del punto 3D (0.5, 0.5, 0.5) se podría encontrar eficientemente con:

SELECT c FROM test ORDER BY c <-> cube(array[0.5,0.5,0.5]) LIMIT 1;

El operador ~> también se puede usar de esta manera para recuperar de forma eficiente los primeros valores ordenados por una coordenada seleccionada. Por ejemplo, para obtener los primeros cubos ordenados por la primera coordenada (esquina inferior izquierda) de forma ascendente, se podría usar la siguiente consulta:

SELECT c FROM test ORDER BY c ~> 1 LIMIT 5;

Y para obtener cubos 2D ordenados por la primera coordenada de la esquina superior derecha de forma descendente:

SELECT c FROM test ORDER BY c ~> 3 DESC LIMIT 5;

La Table F.3 muestra las funciones disponibles.

Table F.3. Funciones de cube

Función

Descripción

Ejemplo(s)

cube ( float8 ) → cube

Crea un cubo unidimensional con ambas coordenadas iguales.

cube(1)(1)

cube ( float8, float8 ) → cube

Crea un cubo unidimensional.

cube(1, 2)(1),(2)

cube ( float8[] ) → cube

Crea un cubo de volumen cero utilizando las coordenadas definidas por el array.

cube(ARRAY[1,2,3])(1, 2, 3)

cube ( float8[], float8[] ) → cube

Crea un cubo con las coordenadas superior derecha e inferior izquierda definidas por los dos arrays, que deben tener la misma longitud.

cube(ARRAY[1,2], ARRAY[3,4])(1, 2),(3, 4)

cube ( cube, float8 ) → cube

Crea un nuevo cubo agregando una dimensión a un cubo existente, con los mismos valores para ambos extremos de la nueva coordenada. Esto es útil para construir cubos pieza por pieza a partir de valores calculados.

cube('(1,2),(3,4)'::cube, 5)(1, 2, 5),(3, 4, 5)

cube ( cube, float8, float8 ) → cube

Crea un nuevo cubo agregando una dimensión a un cubo existente. Esto es útil para construir cubos pieza por pieza a partir de valores calculados.

cube('(1,2),(3,4)'::cube, 5, 6)(1, 2, 5),(3, 4, 6)

cube_dim ( cube ) → integer

Devuelve el número de dimensiones del cubo.

cube_dim('(1,2),(3,4)')2

cube_ll_coord ( cube, integer ) → float8

Devuelve el valor de la n-ésima coordenada para la esquina inferior izquierda del cubo.

cube_ll_coord('(1,2),(3,4)', 2)2

cube_ur_coord ( cube, integer ) → float8

Devuelve el valor de la n-ésima coordenada para la esquina superior derecha del cubo.

cube_ur_coord('(1,2),(3,4)', 2)4

cube_is_point ( cube ) → boolean

Devuelve true si el cubo es un punto, es decir, las dos esquinas definitorias son la misma.

cube_is_point(cube(1,1))t

cube_distance ( cube, cube ) → float8

Devuelve la distancia entre dos cubos. Si ambos cubos son puntos, esta es la función de distancia normal.

cube_distance('(1,2)', '(3,4)')2.8284271247461903

cube_subset ( cube, integer[] ) → cube

Crea un nuevo cubo a partir de un cubo existente, utilizando una lista de índices de dimensiones de un array. Se puede utilizar para extraer los extremos de una sola dimensión, o para eliminar dimensiones, o para reordenarlas según se desee.

cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2])(3),(7)

cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1])(5, 3, 1, 1),(8, 7, 6, 6)

cube_union ( cube, cube ) → cube

Produce la unión de dos cubos.

cube_union('(1,2)', '(3,4)')(1, 2),(3, 4)

cube_inter ( cube, cube ) → cube

Produce la intersección de dos cubos.

cube_inter('(1,2)', '(3,4)')(3, 4),(1, 2)

cube_enlarge ( c cube, r double, n integer ) → cube

Aumenta el tamaño del cubo según el radio r especificado en al menos n dimensiones. Si el radio es negativo, el cubo se reduce. Todas las dimensiones definidas se modifican según el radio r. Las coordenadas inferiores izquierdas disminuyen en r y las coordenadas superiores derechas aumentan en r. Si una coordenada inferior izquierda aumenta más que la correspondiente coordenada superior derecha (esto solo puede ocurrir cuando r < 0), ambas coordenadas se establecen en su promedio. Si n es mayor que el número de dimensiones definidas y el cubo se está agrandando (r > 0), entonces se agregan dimensiones adicionales hasta completar n; se utiliza 0 como valor inicial para las coordenadas adicionales. Esta función es útil para crear cajas delimitadoras alrededor de un punto para buscar puntos cercanos.

cube_enlarge('(1,2),(3,4)', 0.5, 3)(0.5, 1.5, -0.5),(3.5, 4.5, 0.5)


F.10.4. Valores por defecto #

Esta unión:

select cube_union('(0,5,2),(2,3,1)', '0');
cube_union
-------------------
(0, 0, 0),(2, 5, 2)
(1 row)

no contradice el sentido común, ni tampoco la intersección:

select cube_inter('(0,-1),(1,1)', '(-2),(2)');
cube_inter
-------------
(0, 0),(1, 0)
(1 row)

En todas las operaciones binarias sobre cubos de diferentes dimensiones, se asume que el de menor dimensión es una proyección cartesiana, es decir, que tiene ceros en lugar de las coordenadas omitidas en la representación de cadena. Los ejemplos anteriores son equivalentes a:

cube_union('(0,5,2),(2,3,1)','(0,0,0),(0,0,0)');
cube_inter('(0,-1),(1,1)','(-2,0),(2,0)');

El siguiente predicado de contención utiliza la sintaxis de punto, aunque en realidad el segundo argumento está representado internamente por una caja. Esta sintaxis hace que no sea necesario definir un tipo de punto separado y funciones para los predicados (caja, punto).

select cube_contains('(0,0),(1,1)', '0.5,0.5');
cube_contains
--------------
t
(1 row)

F.10.5. Notas #

Para ver ejemplos de uso, consulta el test de regresión sql/cube.sql.

Para evitar que los usuarios rompan cosas, existe un límite de 100 en el número de dimensiones de los cubos. Esto se establece en cubedata.h si necesitas un valor mayor.

F.10.6. Créditos #

Autor original: Gene Selkov, Jr. , División de Matemáticas y Ciencias de la Computación, Laboratorio Nacional de Argonne.

Mi agradecimiento se dirige principalmente al profesor Joe Hellerstein (https://dsf.berkeley.edu/jmh/) por aclarar la esencia de GiST (http://gist.cs.berkeley.edu/), y a su antiguo alumno Andy Dong por su ejemplo escrito para Illustra. También estoy agradecido a todos los desarrolladores de Postgres, presentes y pasados, por permitirme crear mi propio mundo y vivir en él sin ser molestado. Y me gustaría expresar mi gratitud al Laboratorio Argonne y al Departamento de Energía de los EE. UU. por los años de fiel apoyo a mi investigación sobre bases de datos.

Bruno Wolff III realizó actualizaciones menores a este paquete en agosto/septiembre de 2002. Estas incluyen cambiar la precisión de precisión simple a precisión doble y añadir algunas funciones nuevas.

Joshua Reich realizó actualizaciones adicionales en julio de 2006. Estas incluyen cube(float8[], float8[]) y la limpieza del código para usar el protocolo de llamada V1 en lugar del protocolo V0 obsoleto.