BRIN significa Block Range Index (Índice de rango de bloques). BRIN está diseñado para manejar tablas muy grandes en las que ciertas columnas tienen alguna correlación natural con su ubicación física dentro de la tabla.
BRIN funciona en términos de rangos de bloques (o «rangos de páginas»). Un rango de bloques es un grupo de páginas físicamente adyacentes en la tabla; para cada rango de bloques, el índice almacena cierta información resumida. Por ejemplo, una tabla que almacene los pedidos de venta de una tienda podría tener una columna de fecha en la que se realizó cada pedido, y la mayor parte del tiempo las entradas de los pedidos anteriores aparecerán antes en la tabla; una tabla que almacene una columna de código postal podría tener todos los códigos de una ciudad agrupados de forma natural.
Los índices BRIN pueden satisfacer consultas mediante escaneos de índices de mapas de bits (bitmap index scans) regulares, y devolverán todas las tuplas de todas las páginas dentro de cada rango si la información resumida almacenada por el índice es consistente con las condiciones de la consulta. El ejecutor de la consulta se encarga de volver a comprobar estas tuplas y descartar aquellas que no coincidan con las condiciones de la consulta; en otras palabras, estos índices tienen pérdidas (son «lossy»). Debido a que un índice BRIN es muy pequeño, escanear el índice añade poca sobrecarga en comparación con un escaneo secuencial, pero puede evitar escanear grandes partes de la tabla que se sabe que no contienen tuplas coincidentes.
Los datos específicos que almacenará un índice BRIN, así como las consultas específicas que el índice podrá satisfacer, dependen de la clase de operadores seleccionada para cada columna del índice. Los tipos de datos que tienen un orden de clasificación lineal pueden tener clases de operadores que almacenen el valor mínimo y máximo dentro de cada rango de bloques, por ejemplo; los tipos geométricos podrían almacenar la caja delimitadora (bounding box) de todos los objetos en el rango de bloques.
El tamaño del rango de bloques se determina en el momento de la creación del índice mediante el
parámetro de almacenamiento pages_per_range. El número de entradas del índice será
igual al tamaño de la relación en páginas dividido por el valor seleccionado para
pages_per_range. Por lo tanto, cuanto menor sea el número, mayor se volverá el
índice (debido a la necesidad de almacenar más entradas de índice), pero al mismo tiempo los datos
de resumen almacenados pueden ser más precisos y se pueden omitir más bloques de datos durante el
escaneo de un índice.
En el momento de la creación, se escanean todas las páginas de la tabla y se crea una tupla de índice de resumen para cada rango, incluyendo el rango posiblemente incompleto al final. A medida que se llenan nuevas páginas con datos, los rangos de páginas que ya están resumidos harán que se actualice la información de resumen con los datos de las nuevas tuplas. Cuando se crea una nueva página que no cae dentro del último rango resumido, el rango al que pertenece la nueva página no adquiere automáticamente una tupla de resumen; esas tuplas permanecen sin resumir hasta que se invoque una ejecución de resumen más adelante, creando el resumen inicial para ese rango.
Hay varias formas de desencadenar el resumen inicial de un rango de páginas. Si la tabla es vacumada, ya sea manualmente o por autovacuum, se resumen todos los rangos de páginas no resumidos existentes. Además, si el parámetro autosummarize del índice está activado, lo cual no ocurre por defecto, cada vez que se ejecute autovacuum en esa base de datos, se realizará el resumen para todos los rangos de páginas no resumidos que se hayan llenado, independientemente de si la propia tabla es procesada por autovacuum; ver más abajo.
Por último, se pueden utilizar las siguientes funciones (mientras estas funciones se ejecutan,
search_path se cambia temporalmente a
pg_catalog, pg_temp):
brin_summarize_new_values(regclass)
que resume todos los rangos no resumidos;
|
brin_summarize_range(regclass, bigint)
que resume solo el rango que contiene la página dada, si no está resumido.
|
Cuando el resumen automático (autosummarization) está activado, se envía una solicitud a
autovacuum para ejecutar un resumen específico para un rango de bloques cuando
se detecta una inserción para el primer elemento de la primera página del siguiente rango de bloques,
para ser cumplida la próxima vez que un trabajador de autovacuum termine de ejecutarse en la misma
base de datos. Si la cola de solicitudes está llena, la solicitud no se registra y se envía un mensaje
al log del servidor:
LOG: request for BRIN range summarization for index "brin_wi_idx" page 128 was not recorded
Cuando esto sucede, el rango permanecerá sin resumir hasta la siguiente ejecución regular de vacuum en la tabla, o hasta que se invoque una de las funciones mencionadas anteriormente.
Por el contrario, se puede anular el resumen de un rango utilizando la función
brin_desummarize_range(regclass, bigint), lo cual es útil cuando la tupla
del índice ya no es una representación muy buena porque los valores existentes han cambiado.
Consulta Section 9.28.8 para más detalles.
La distribución principal de PostgreSQL incluye las clases de operadores BRIN que se muestran en Table 65.4.
Las clases de operadores minmax almacenan los valores mínimos y máximos que aparecen en la columna indexada dentro del rango. Las clases de operadores de inclusion (inclusión) almacenan un valor que incluye los valores de la columna indexada dentro del rango. Las clases de operadores bloom construyen un filtro de Bloom para todos los valores del rango. Las clases de operadores minmax-multi almacenan múltiples valores mínimos y máximos, representando los valores que aparecen en la columna indexada dentro del rango.
Table 65.4. Clases de operadores BRIN integradas
| Nombre | Operadores indexables |
|---|---|
bit_minmax_ops | = (bit,bit) |
< (bit,bit) | |
> (bit,bit) | |
<= (bit,bit) | |
>= (bit,bit) | |
box_inclusion_ops | @> (box,point) |
<< (box,box) | |
&< (box,box) | |
&> (box,box) | |
>> (box,box) | |
<@ (box,box) | |
@> (box,box) | |
~= (box,box) | |
&& (box,box) | |
<<| (box,box) | |
&<| (box,box) | |
|&> (box,box) | |
|>> (box,box) | |
bpchar_bloom_ops | = (character,character) |
bpchar_minmax_ops | = (character,character) |
< (character,character) | |
<= (character,character) | |
> (character,character) | |
>= (character,character) | |
bytea_bloom_ops | = (bytea,bytea) |
bytea_minmax_ops | = (bytea,bytea) |
< (bytea,bytea) | |
<= (bytea,bytea) | |
> (bytea,bytea) | |
>= (bytea,bytea) | |
char_bloom_ops | = ("char","char") |
char_minmax_ops | = ("char","char") |
< ("char","char") | |
<= ("char","char") | |
> ("char","char") | |
>= ("char","char") | |
date_bloom_ops | = (date,date) |
date_minmax_ops | = (date,date) |
< (date,date) | |
<= (date,date) | |
> (date,date) | |
>= (date,date) | |
date_minmax_multi_ops | = (date,date) |
< (date,date) | |
<= (date,date) | |
> (date,date) | |
>= (date,date) | |
float4_bloom_ops | = (float4,float4) |
float4_minmax_ops | = (float4,float4) |
< (float4,float4) | |
> (float4,float4) | |
<= (float4,float4) | |
>= (float4,float4) | |
float4_minmax_multi_ops | = (float4,float4) |
< (float4,float4) | |
> (float4,float4) | |
<= (float4,float4) | |
>= (float4,float4) | |
float8_bloom_ops | = (float8,float8) |
float8_minmax_ops | = (float8,float8) |
< (float8,float8) | |
<= (float8,float8) | |
> (float8,float8) | |
>= (float8,float8) | |
float8_minmax_multi_ops | = (float8,float8) |
< (float8,float8) | |
<= (float8,float8) | |
> (float8,float8) | |
>= (float8,float8) | |
inet_inclusion_ops | << (inet,inet) |
<<= (inet,inet) | |
>> (inet,inet) | |
>>= (inet,inet) | |
= (inet,inet) | |
&& (inet,inet) | |
inet_bloom_ops | = (inet,inet) |
inet_minmax_ops | = (inet,inet) |
< (inet,inet) | |
<= (inet,inet) | |
> (inet,inet) | |
>= (inet,inet) | |
inet_minmax_multi_ops | = (inet,inet) |
< (inet,inet) | |
<= (inet,inet) | |
> (inet,inet) | |
>= (inet,inet) | |
int2_bloom_ops | = (int2,int2) |
int2_minmax_ops | = (int2,int2) |
< (int2,int2) | |
> (int2,int2) | |
<= (int2,int2) | |
>= (int2,int2) | |
int2_minmax_multi_ops | = (int2,int2) |
< (int2,int2) | |
> (int2,int2) | |
<= (int2,int2) | |
>= (int2,int2) | |
int4_bloom_ops | = (int4,int4) |
int4_minmax_ops | = (int4,int4) |
< (int4,int4) | |
> (int4,int4) | |
<= (int4,int4) | |
>= (int4,int4) | |
int4_minmax_multi_ops | = (int4,int4) |
< (int4,int4) | |
> (int4,int4) | |
<= (int4,int4) | |
>= (int4,int4) | |
int8_bloom_ops | = (bigint,bigint) |
int8_minmax_ops | = (bigint,bigint) |
< (bigint,bigint) | |
> (bigint,bigint) | |
<= (bigint,bigint) | |
>= (bigint,bigint) | |
int8_minmax_multi_ops | = (bigint,bigint) |
< (bigint,bigint) | |
> (bigint,bigint) | |
<= (bigint,bigint) | |
>= (bigint,bigint) | |
interval_bloom_ops | = (interval,interval) |
interval_minmax_ops | = (interval,interval) |
< (interval,interval) | |
<= (interval,interval) | |
> (interval,interval) | |
>= (interval,interval) | |
interval_minmax_multi_ops | = (interval,interval) |
< (interval,interval) | |
<= (interval,interval) | |
> (interval,interval) | |
>= (interval,interval) | |
macaddr_bloom_ops | = (macaddr,macaddr) |
macaddr_minmax_ops | = (macaddr,macaddr) |
< (macaddr,macaddr) | |
<= (macaddr,macaddr) | |
> (macaddr,macaddr) | |
>= (macaddr,macaddr) | |
macaddr_minmax_multi_ops | = (macaddr,macaddr) |
< (macaddr,macaddr) | |
<= (macaddr,macaddr) | |
> (macaddr,macaddr) | |
>= (macaddr,macaddr) | |
macaddr8_bloom_ops | = (macaddr8,macaddr8) |
macaddr8_minmax_ops | = (macaddr8,macaddr8) |
< (macaddr8,macaddr8) | |
<= (macaddr8,macaddr8) | |
> (macaddr8,macaddr8) | |
>= (macaddr8,macaddr8) | |
macaddr8_minmax_multi_ops | = (macaddr8,macaddr8) |
< (macaddr8,macaddr8) | |
<= (macaddr8,macaddr8) | |
> (macaddr8,macaddr8) | |
>= (macaddr8,macaddr8) | |
name_bloom_ops | = (name,name) |
name_minmax_ops | = (name,name) |
< (name,name) | |
<= (name,name) | |
> (name,name) | |
>= (name,name) | |
numeric_bloom_ops | = (numeric,numeric) |
numeric_minmax_ops | = (numeric,numeric) |
< (numeric,numeric) | |
<= (numeric,numeric) | |
> (numeric,numeric) | |
>= (numeric,numeric) | |
numeric_minmax_multi_ops | = (numeric,numeric) |
< (numeric,numeric) | |
<= (numeric,numeric) | |
> (numeric,numeric) | |
>= (numeric,numeric) | |
oid_bloom_ops | = (oid,oid) |
oid_minmax_ops | = (oid,oid) |
< (oid,oid) | |
> (oid,oid) | |
<= (oid,oid) | |
>= (oid,oid) | |
oid_minmax_multi_ops | = (oid,oid) |
< (oid,oid) | |
> (oid,oid) | |
<= (oid,oid) | |
>= (oid,oid) | |
pg_lsn_bloom_ops | = (pg_lsn,pg_lsn) |
pg_lsn_minmax_ops | = (pg_lsn,pg_lsn) |
< (pg_lsn,pg_lsn) | |
> (pg_lsn,pg_lsn) | |
<= (pg_lsn,pg_lsn) | |
>= (pg_lsn,pg_lsn) | |
pg_lsn_minmax_multi_ops | = (pg_lsn,pg_lsn) |
< (pg_lsn,pg_lsn) | |
> (pg_lsn,pg_lsn) | |
<= (pg_lsn,pg_lsn) | |
>= (pg_lsn,pg_lsn) | |
range_inclusion_ops | = (anyrange,anyrange) |
< (anyrange,anyrange) | |
<= (anyrange,anyrange) | |
>= (anyrange,anyrange) | |
> (anyrange,anyrange) | |
&& (anyrange,anyrange) | |
@> (anyrange,anyelement) | |
@> (anyrange,anyrange) | |
<@ (anyrange,anyrange) | |
<< (anyrange,anyrange) | |
>> (anyrange,anyrange) | |
&< (anyrange,anyrange) | |
&> (anyrange,anyrange) | |
-|- (anyrange,anyrange) | |
text_bloom_ops | = (text,text) |
text_minmax_ops | = (text,text) |
< (text,text) | |
<= (text,text) | |
> (text,text) | |
>= (text,text) | |
tid_bloom_ops | = (tid,tid) |
tid_minmax_ops | = (tid,tid) |
< (tid,tid) | |
> (tid,tid) | |
<= (tid,tid) | |
>= (tid,tid) | |
tid_minmax_multi_ops | = (tid,tid) |
< (tid,tid) | |
> (tid,tid) | |
<= (tid,tid) | |
>= (tid,tid) | |
timestamp_bloom_ops | = (timestamp,timestamp) |
timestamp_minmax_ops | = (timestamp,timestamp) |
< (timestamp,timestamp) | |
<= (timestamp,timestamp) | |
> (timestamp,timestamp) | |
>= (timestamp,timestamp) | |
timestamp_minmax_multi_ops | = (timestamp,timestamp) |
< (timestamp,timestamp) | |
<= (timestamp,timestamp) | |
> (timestamp,timestamp) | |
>= (timestamp,timestamp) | |
timestamptz_bloom_ops | = (timestamptz,timestamptz) |
timestamptz_minmax_ops | = (timestamptz,timestamptz) |
< (timestamptz,timestamptz) | |
<= (timestamptz,timestamptz) | |
> (timestamptz,timestamptz) | |
>= (timestamptz,timestamptz) | |
timestamptz_minmax_multi_ops | = (timestamptz,timestamptz) |
< (timestamptz,timestamptz) | |
<= (timestamptz,timestamptz) | |
> (timestamptz,timestamptz) | |
>= (timestamptz,timestamptz) | |
time_bloom_ops | = (time,time) |
time_minmax_ops | = (time,time) |
< (time,time) | |
<= (time,time) | |
> (time,time) | |
>= (time,time) | |
time_minmax_multi_ops | = (time,time) |
< (time,time) | |
<= (time,time) | |
> (time,time) | |
>= (time,time) | |
timetz_bloom_ops | = (timetz,timetz) |
timetz_minmax_ops | = (timetz,timetz) |
< (timetz,timetz) | |
<= (timetz,timetz) | |
> (timetz,timetz) | |
>= (timetz,timetz) | |
timetz_minmax_multi_ops | = (timetz,timetz) |
< (timetz,timetz) | |
<= (timetz,timetz) | |
> (timetz,timetz) | |
>= (timetz,timetz) | |
uuid_bloom_ops | = (uuid,uuid) |
uuid_minmax_ops | = (uuid,uuid) |
< (uuid,uuid) | |
> (uuid,uuid) | |
<= (uuid,uuid) | |
>= (uuid,uuid) | |
uuid_minmax_multi_ops | = (uuid,uuid) |
< (uuid,uuid) | |
> (uuid,uuid) | |
<= (uuid,uuid) | |
>= (uuid,uuid) | |
varbit_minmax_ops | = (varbit,varbit) |
< (varbit,varbit) | |
> (varbit,varbit) | |
<= (varbit,varbit) | |
>= (varbit,varbit) |
Algunas de las clases de operadores integradas permiten especificar parámetros que afectan al
comportamiento de la clase de operadores. Cada clase de operadores tiene su propio conjunto de
parámetros permitidos. Solo las clases de operadores bloom y
minmax-multi permiten especificar parámetros:
Las clases de operadores bloom aceptan estos parámetros:
n_distinct_per_range
Define el número estimado de valores distintos no nulos en el rango de bloques, utilizado por los
índices bloom de BRIN para dimensionar el filtro de Bloom. Se comporta de forma
similar a la opción n_distinct para ALTER TABLE. Cuando se
establece en un valor positivo, se asume que cada rango de bloques contiene este número de valores
distintos no nulos. Cuando se establece en un valor negativo, que debe ser mayor o igual que -1, se
asume que el número de valores distintos no nulos crece linealmente con el número máximo posible de tuplas
en el rango de bloques (alrededor de 290 filas por bloque). El valor por defecto es -0.1,
y el número mínimo de valores distintos no nulos es 16.
false_positive_rateDefine la tasa de falsos positivos deseada utilizada por los índices bloom de BRIN para dimensionar el filtro de Bloom. Los valores deben estar entre 0.0001 y 0.25. El valor por defecto es 0.01, que representa una tasa de falsos positivos del 1%.
Las clases de operadores minmax-multi aceptan estos parámetros:
values_per_rangeDefine el número máximo de valores almacenados por los índices minmax de BRIN para resumir un rango de bloques. Cada valor puede representar un punto o un límite de un intervalo. Los valores deben estar entre 8 y 256, y el valor por defecto es 32.
La interfaz de BRIN tiene un alto nivel de abstracción, lo que requiere que el implementador del método de acceso solo implemente la semántica del tipo de datos al que se accede. La propia capa de BRIN se encarga de la concurrencia, el registro y la búsqueda en la estructura del índice.
Todo lo que se necesita para poner en funcionamiento un método de acceso BRIN es implementar unos pocos métodos definidos por el usuario, que definen el comportamiento de los valores de resumen almacenados en el índice y la forma en que interactúan con las claves de escaneo (scan keys). En resumen, BRIN combina extensibilidad con generalidad, reutilización de código y una interfaz limpia.
Hay cuatro métodos que debe proporcionar una clase de operadores para BRIN:
BrinOpcInfo *opcInfo(Oid type_oid)
Devuelve información interna sobre los datos de resumen de las columnas indexadas. El valor de retorno debe
apuntar a un BrinOpcInfo asignado mediante palloc, el cual tiene esta definición:
typedef struct BrinOpcInfo
{
/* Number of columns stored in an index column of this opclass */
uint16 oi_nstored;
/* Opaque pointer for the opclass' private use */
void *oi_opaque;
/* Type cache entries of the stored columns */
TypeCacheEntry *oi_typcache[FLEXIBLE_ARRAY_MEMBER];
} BrinOpcInfo;
Las rutinas de la clase de operadores pueden utilizar
BrinOpcInfo.oi_opaque para pasar información entre las
funciones de soporte durante el escaneo de un índice.
bool consistent(BrinDesc *bdesc, BrinValues *column,
ScanKey *keys, int nkeys)
Devuelve si todas las entradas de ScanKey son consistentes con los valores indexados dados para un rango.
El número de atributo a utilizar se pasa como parte de la clave de escaneo. Se pueden pasar múltiples claves de
escaneo para el mismo atributo a la vez; el número de entradas viene determinado por el parámetro
nkeys.
bool consistent(BrinDesc *bdesc, BrinValues *column,
ScanKey key)Devuelve si el ScanKey es consistente con los valores indexados dados para un rango. El número de atributo a utilizar se pasa como parte de la clave de escaneo. Esta es una variante antigua de la función consistent, mantenida por compatibilidad hacia atrás.
bool addValue(BrinDesc *bdesc, BrinValues *column,
Datum newval, bool isnull)
Dada una tupla de índice y un valor indexado, modifica el atributo indicado de la tupla para que represente
adicionalmente el nuevo valor. Si se realizó alguna modificación en la tupla, se devuelve true.
bool unionTuples(BrinDesc *bdesc, BrinValues *a,
BrinValues *b)Consolida dos tuplas de índice. Dadas dos tuplas de índice, modifica el atributo indicado de la primera de ellas para que represente ambas tuplas. La segunda tupla no se modifica.
Una clase de operadores para BRIN puede especificar opcionalmente el siguiente método:
void options(local_relopts *relopts)Define un conjunto de parámetros visibles para el usuario que controlan el comportamiento de la clase de operadores.
A la función options se le pasa un puntero a una estructura
local_relopts, que debe llenarse con un conjunto de opciones específicas de la
clase de operadores. Se puede acceder a las opciones desde otras funciones de soporte utilizando las
macros PG_HAS_OPCLASS_OPTIONS() y PG_GET_OPCLASS_OPTIONS().
Dado que tanto la extracción de claves de los valores indexados como la representación de la clave en BRIN son flexibles, estas pueden depender de parámetros especificados por el usuario.
La distribución principal incluye soporte para cuatro tipos de clases de operadores: minmax, minmax-multi, inclusion y bloom. Las definiciones de clases de operadores que las utilizan se distribuyen para los tipos de datos integrados según corresponda. El usuario puede definir clases de operadores adicionales para otros tipos de datos utilizando definiciones equivalentes, sin tener que escribir ningún código fuente; es suficiente con declarar las entradas correspondientes en el catálogo. Ten en cuenta que las suposiciones sobre la semántica de las estrategias de los operadores están integradas en el código fuente de las funciones de soporte.
También son posibles clases de operadores que implementen semánticas completamente diferentes, siempre que se escriban las implementaciones de las cuatro funciones de soporte principales descritas anteriormente. Ten en cuenta que no se garantiza la compatibilidad hacia atrás entre versiones principales: por ejemplo, en versiones posteriores podrían requerirse funciones de soporte adicionales.
Para escribir una clase de operadores para un tipo de datos que implementa un conjunto totalmente ordenado, es posible utilizar las funciones de soporte de minmax junto con los operadores correspondientes, como se muestra en Table 65.5. Todos los miembros de la clase de operadores (funciones y operadores) son obligatorios.
Table 65.5. Números de función y soporte para clases de operadores Minmax
| Miembro de la clase de operadores | Objeto |
|---|---|
| Función de soporte 1 | función interna brin_minmax_opcinfo() |
| Función de soporte 2 | función interna brin_minmax_add_value() |
| Función de soporte 3 | función interna brin_minmax_consistent() |
| Función de soporte 4 | función interna brin_minmax_union() |
| Estrategia de operador 1 | operador menor que |
| Estrategia de operador 2 | operador menor o igual que |
| Estrategia de operador 3 | operador igual a |
| Estrategia de operador 4 | operador mayor o igual que |
| Estrategia de operador 5 | operador mayor que |
Para escribir una clase de operadores para un tipo de datos complejo que tiene valores incluidos dentro de otro tipo, es posible utilizar las funciones de soporte de inclusión junto con los operadores correspondientes, como se muestra en Table 65.6. Requiere solo una función adicional, que se puede escribir en cualquier lenguaje. Se pueden definir más funciones para obtener funcionalidades adicionales. Todos los operadores son opcionales. Algunos operadores requieren otros operadores, como se muestra en las dependencias de la tabla.
Table 65.6. Números de función y soporte para clases de operadores de inclusión
| Miembro de la clase de operadores | Objeto | Dependencia |
|---|---|---|
| Función de soporte 1 | función interna brin_inclusion_opcinfo() | |
| Función de soporte 2 | función interna brin_inclusion_add_value() | |
| Función de soporte 3 | función interna brin_inclusion_consistent() | |
| Función de soporte 4 | función interna brin_inclusion_union() | |
| Función de soporte 11 | función para fusionar dos elementos | |
| Función de soporte 12 | función opcional para comprobar si dos elementos son fusionables | |
| Función de soporte 13 | función opcional para comprobar si un elemento está contenido dentro de otro | |
| Función de soporte 14 | función opcional para comprobar si un elemento está vacío | |
| Estrategia de operador 1 | operador a la izquierda de | Estrategia de operador 4 |
| Estrategia de operador 2 | operador no se extiende a la derecha de | Estrategia de operador 5 |
| Estrategia de operador 3 | operador se solapa con (overlaps) | |
| Estrategia de operador 4 | operador no se extiende a la izquierda de | Estrategia de operador 1 |
| Estrategia de operador 5 | operador a la derecha de | Estrategia de operador 2 |
| Estrategia de operador 6, 18 | operador idéntico a o igual a | Estrategia de operador 7 |
| Estrategia de operador 7, 16, 24, 25 | operador contiene o igual a | |
| Estrategia de operador 8, 26, 27 | operador está contenido por o igual a | Estrategia de operador 3 |
| Estrategia de operador 9 | operador no se extiende por encima de | Estrategia de operador 11 |
| Estrategia de operador 10 | operador está por debajo de | Estrategia de operador 12 |
| Estrategia de operador 11 | operador está por encima de | Estrategia de operador 9 |
| Estrategia de operador 12 | operador no se extiende por debajo de | Estrategia de operador 10 |
| Estrategia de operador 20 | operador menor que | Estrategia de operador 5 |
| Estrategia de operador 21 | operador menor o igual que | Estrategia de operador 5 |
| Estrategia de operador 22 | operador mayor que | Estrategia de operador 1 |
| Estrategia de operador 23 | operador mayor o igual que | Estrategia de operador 1 |
Los números de las funciones de soporte del 1 al 10 están reservados para las funciones internas de BRIN,
por lo que las funciones a nivel de SQL comienzan con el número 11. La función de soporte número 11 es la función
principal requerida para construir el índice. Debe aceptar dos argumentos con el mismo tipo de datos que la
clase de operadores y devolver la unión de ellos. La clase de operadores de inclusión puede almacenar valores de
unión con diferentes tipos de datos si se define con el parámetro STORAGE. El valor de retorno
de la función de unión debe coincidir con el tipo de datos de STORAGE.
Los números de función de soporte 12 y 14 se proporcionan para dar soporte a irregularidades de los tipos de datos integrados. La función número 12 se utiliza para dar soporte a direcciones de red de diferentes familias que no son fusionables. La función número 14 se utiliza para dar soporte a rangos vacíos. La función número 13 es una función opcional pero recomendada, que permite comprobar el nuevo valor antes de pasarlo a la función de unión. Como el framework BRIN puede omitir algunas operaciones cuando la unión no cambia, el uso de esta función puede mejorar el rendimiento del índice.
Para escribir una clase de operadores para un tipo de datos que implementa solo un operador de igualdad y soporta hashing, es posible utilizar los procedimientos de soporte de bloom junto con los operadores correspondientes, como se muestra en Table 65.7. Todos los miembros de la clase de operadores (procedimientos y operadores) son obligatorios.
Table 65.7. Procedimiento y números de soporte para clases de operadores Bloom
| Miembro de la clase de operadores | Objeto |
|---|---|
| Procedimiento de soporte 1 | función interna brin_bloom_opcinfo() |
| Procedimiento de soporte 2 | función interna brin_bloom_add_value() |
| Procedimiento de soporte 3 | función interna brin_bloom_consistent() |
| Procedimiento de soporte 4 | función interna brin_bloom_union() |
| Procedimiento de soporte 5 | función interna brin_bloom_options() |
| Procedimiento de soporte 11 | función para calcular el hash de un elemento |
| Estrategia de operador 1 | operador igual a |
Los números de procedimientos de soporte 1-10 están reservados para las funciones internas de BRIN, por lo que las funciones a nivel de SQL comienzan con el número 11. La función de soporte número 11 es la función principal requerida para construir el índice. Debe aceptar un argumento con el mismo tipo de datos que la clase de operadores y devolver un hash del valor.
La clase de operadores minmax-multi también está pensada para tipos de datos que implementan un conjunto totalmente ordenado, y puede verse como una extensión simple de la clase de operadores minmax. Mientras que la clase de operadores minmax resume los valores de cada rango de bloques en un único intervalo contiguo, minmax-multi permite resumirlos en múltiples intervalos más pequeños para mejorar la gestión de los valores atípicos (outliers). Es posible utilizar los procedimientos de soporte de minmax-multi junto con los operadores correspondientes, como se muestra en Table 65.8. Todos los miembros de la clase de operadores (procedimientos y operadores) son obligatorios.
Table 65.8. Procedimiento y números de soporte para clases de operadores minmax-multi
| Miembro de la clase de operadores | Objeto |
|---|---|
| Procedimiento de soporte 1 | función interna brin_minmax_multi_opcinfo() |
| Procedimiento de soporte 2 | función interna brin_minmax_multi_add_value() |
| Procedimiento de soporte 3 | función interna brin_minmax_multi_consistent() |
| Procedimiento de soporte 4 | función interna brin_minmax_multi_union() |
| Procedimiento de soporte 5 | función interna brin_minmax_multi_options() |
| Procedimiento de soporte 11 | función para calcular la distancia entre dos valores (longitud de un rango) |
| Estrategia de operador 1 | operador menor que |
| Estrategia de operador 2 | operador menor o igual que |
| Estrategia de operador 3 | operador igual a |
| Estrategia de operador 4 | operador mayor o igual que |
| Estrategia de operador 5 | operador mayor que |
Tanto la clase de operadores minmax como la de inclusión soportan operadores entre distintos tipos de datos, aunque
con estos las dependencias se vuelven más complicadas. La clase de operadores minmax requiere que se defina un
conjunto completo de operadores en los que ambos argumentos tengan el mismo tipo de datos. Permite soportar tipos
de datos adicionales definiendo conjuntos adicionales de operadores. Las estrategias de operador de la clase de
operadores de inclusión dependen de otra estrategia de operador, como se muestra en
Table 65.6, o de la misma estrategia de operador que ellas mismas.
Requieren que el operador de dependencia se defina con el tipo de datos STORAGE como el argumento
del lado izquierdo y el otro tipo de datos soportado como el argumento del lado derecho del operador soportado.
Consulta float4_minmax_ops como un ejemplo de minmax, y box_inclusion_ops
como un ejemplo de inclusión.