F.19. intarray — manipular arrays de enteros #

F.19.1. Funciones y operadores de intarray
F.19.2. Soporte de índices
F.19.3. Ejemplo
F.19.4. Prueba de rendimiento (Benchmark)
F.19.5. Autores

El módulo intarray proporciona una serie de funciones y operadores útiles para manipular arrays de enteros libres de valores nulos (null-free). También existe soporte para búsquedas indexadas utilizando algunos de los operadores.

Todas estas operaciones lanzarán un error si un array proporcionado contiene algún elemento NULL.

Muchas de estas operaciones solo tienen sentido para arrays unidimensionales. Aunque aceptarán arrays de entrada de más dimensiones, los datos se tratan como si fueran un array lineal en el orden de almacenamiento.

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

F.19.1. Funciones y operadores de intarray #

Las funciones proporcionadas por el módulo intarray se muestran en la Table F.8, y los operadores en la Table F.9.

Table F.8. Funciones de intarray

Función

Descripción

Ejemplo(s)

icount ( integer[] ) → integer

Devuelve el número de elementos en el array.

icount('{1,2,3}'::integer[])3

sort ( integer[], dir text ) → integer[]

Ordena el array en orden ascendente o descendente. dir debe ser asc o desc.

sort('{1,3,2}'::integer[], 'desc'){3,2,1}

sort ( integer[] ) → integer[]

sort_asc ( integer[] ) → integer[]

Ordena en orden ascendente.

sort(array[11,77,44]){11,44,77}

sort_desc ( integer[] ) → integer[]

Ordena en orden descendente.

sort_desc(array[11,77,44]){77,44,11}

uniq ( integer[] ) → integer[]

Elimina duplicados adyacentes. A menudo se usa con sort para eliminar todos los duplicados.

uniq('{1,2,2,3,1,1}'::integer[]){1,2,3,1}

uniq(sort('{1,2,3,2,1}'::integer[])){1,2,3}

idx ( integer[], item integer ) → integer

Devuelve el índice del primer elemento del array que coincide con item, o 0 si no hay coincidencia.

idx(array[11,22,33,22,11], 22)2

subarray ( integer[], start integer, len integer ) → integer[]

Extrae la parte del array que comienza en la posición start, con len elementos.

subarray('{1,2,3,2,1}'::integer[], 2, 3){2,3,2}

subarray ( integer[], start integer ) → integer[]

Extrae la parte del array que comienza en la posición start.

subarray('{1,2,3,2,1}'::integer[], 2){2,3,2,1}

intset ( integer ) → integer[]

Crea un array de un solo elemento.

intset(42){42}


Table F.9. Operadores de intarray

Operador

Descripción

integer[] && integer[]boolean

¿Se superponen los arrays (tienen al menos un elemento en común)?

integer[] @> integer[]boolean

¿El array izquierdo contiene al array derecho?

integer[] <@ integer[]boolean

¿El array izquierdo está contenido en el array derecho?

# integer[]integer

Devuelve el número de elementos en el array.

integer[] # integerinteger

Devuelve el índice del primer elemento del array que coincide con el argumento derecho, o 0 si no hay coincidencia. (Igual que la función idx).

integer[] + integerinteger[]

Agrega un elemento al final del array.

integer[] + integer[]integer[]

Concatena los arrays.

integer[] - integerinteger[]

Elimina las entradas que coinciden con el argumento derecho del array.

integer[] - integer[]integer[]

Elimina los elementos del array derecho del array izquierdo.

integer[] | integerinteger[]

Calcula la unión de los argumentos.

integer[] | integer[]integer[]

Calcula la unión de los argumentos.

integer[] & integer[]integer[]

Calcula la intersección de los argumentos.

integer[] @@ query_intboolean

¿El array satisface la consulta? (ver abajo)

query_int ~~ integer[]boolean

¿El array satisface la consulta? (conmutador de @@)


Los operadores &&, @> y <@ son equivalentes a los operadores integrados de PostgreSQL con los mismos nombres, excepto que funcionan solo en arrays de enteros que no contienen nulos, mientras que los operadores integrados funcionan para cualquier tipo de array. Esta restricción los hace más rápidos que los operadores integrados en muchos casos.

Los operadores @@ y ~~ comprueban si un array satisface una consulta (query), la cual se expresa como un valor de un tipo de datos especializado query_int. Una consulta consiste en valores enteros que se verifican contra los elementos del array, posiblemente combinados utilizando los operadores & (AND), | (OR) y ! (NOT). Se pueden usar paréntesis según sea necesario. Por ejemplo, la consulta 1&(2|3) coincide con arrays que contienen 1 y además contienen 2 o 3.

F.19.2. Soporte de índices #

intarray proporciona soporte de índices para los operadores &&, @> y @@, así como para la igualdad de arrays regular.

Se proporcionan dos clases de operadores de índice GiST parametrizados: gist__int_ops (usada por defecto) es adecuada para conjuntos de datos pequeños a medianos, mientras que gist__intbig_ops utiliza una firma más grande y es más adecuada para indexar grandes conjuntos de datos (es decir, columnas que contienen una gran cantidad de valores de array distintos). La implementación utiliza una estructura de datos RD-tree con compresión con pérdida integrada.

gist__int_ops aproxima un conjunto de enteros como un array de rangos de enteros. Su parámetro entero opcional numranges determina el número máximo de rangos en una clave de índice. El valor por defecto de numranges es 100. Los valores válidos están entre 1 y 253. El uso de arrays más grandes como claves de índice GiST conduce a una búsqueda más precisa (escaneando una fracción más pequeña del índice y menos páginas de almacenamiento), a costa de un índice más grande.

gist__intbig_ops aproxima un conjunto de enteros como una firma de mapa de bits. Su parámetro entero opcional siglen determina la longitud de la firma en bytes. La longitud de firma por defecto es 16 bytes. Los valores válidos de longitud de firma están entre 1 y 2024 bytes. Las firmas más largas conducen a una búsqueda más precisa (escaneando una fracción más pequeña del índice y menos páginas de almacenamiento), a costa de un índice más grande.

También existe una clase de operador GIN no predeterminada, gin__int_ops, que admite estos operadores, así como <@.

La elección entre indexación GiST y GIN depende de las características de rendimiento relativo de GiST y GIN, las cuales se discuten en otra sección.

F.19.3. Ejemplo #

-- un mensaje puede estar en una o más «secciones»
CREATE TABLE message (mid INT PRIMARY KEY, sections INT[], ...);

-- crear un índice especializado con una longitud de firma de 32 bytes
CREATE INDEX message_rdtree_idx ON message USING GIST (sections gist__intbig_ops (siglen = 32));

-- seleccionar mensajes en la sección 1 O 2 - operador de SUPERPOSICIÓN (OVERLAP)
SELECT message.mid FROM message WHERE message.sections && '{1,2}';

-- seleccionar mensajes en las secciones 1 Y 2 - operador CONTIENE (CONTAINS)
SELECT message.mid FROM message WHERE message.sections @> '{1,2}';

-- lo mismo, utilizando el operador QUERY
SELECT message.mid FROM message WHERE message.sections @@ '1&2'::query_int;

F.19.4. Prueba de rendimiento (Benchmark) #

El directorio de fuentes contrib/intarray/bench contiene un conjunto de pruebas de rendimiento, el cual se puede ejecutar contra un servidor PostgreSQL instalado. (También requiere que esté instalado DBD::Pg). Para ejecutarlo:

cd .../contrib/intarray/bench
createdb TEST
psql -c "CREATE EXTENSION intarray" TEST
./create_test.pl | psql TEST
./bench.pl

El script bench.pl tiene numerosas opciones, que se muestran cuando se ejecuta sin ningún argumento.

F.19.5. Autores #

Todo el trabajo fue realizado por Teodor Sigaev () y Oleg Bartunov (). Consulta http://www.sai.msu.su/~megera/postgres/gist/ para obtener información adicional. Andrey Oktyabrski realizó un gran trabajo al agregar nuevas funciones y operaciones.