Creando Hash en tablas para mejorar rendimiento
Creando hash en tabla para mejorar rendimiento
ARTICULO AUN EN REVISIÓN Y PROCESO DE DEPURACIÓN.
Este artículo implementa una técnica poco convencional para mejorar la performance de las querys creando un hash de los campos de texto de nuestras tablas. Esto sirve para busquedas exactas, si lo que quieren es busqueda de palabras deberán leer un poco más de TSearch (incluido en Pgsql84).
Utilizando CRC32
Creamos un archivo llamado crc.c y guardamos el siguiente código en el archivo:
/*
* CYCLIC REDUNDANCY CHECK
*/
#include "postgres.h"
#include "fmgr.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
PG_FUNCTION_INFO_V1(pg_crc_simple);
Datum
pg_crc_simple(PG_FUNCTION_ARGS){
char *message = PG_GETARG_TEXT_P(0);
//size_t argumentlen = VARSIZE(message)-VARHDRSZ;
int i, j;
unsigned int byte, crc, mask;
int32 normalize;
static unsigned int table[256];
/* Seteamos la tabla de ser necesario. */
if (table[1] == 0) {
for (byte = 0; byte <= 255; byte++) {
crc = byte;
for (j = 7; j >= 0; j--) { // 8veces
mask = -(crc & 1);
crc = (crc >> 1) ^ (0xEDB88320 & mask);
}
table[byte] = crc;
}
}
/* tenemos la tabla y calculamos*/
i = 0;
crc = 0xFFFFFFFF;
while (message[i] != 0) {
byte = message[i]; // Get next byte.
crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
i = i + 1;
}
normalize = -(~crc);
PG_RETURN_INT32(normalize);
}
Luego lo compilamos como un shared object:
gcc -I $DIRECTORIO_POSTGRES/include/server/ --shared crc.c
Luego, tenemos que incluir esa función en el motor:
CREATE OR REPLACE FUNCTION pg_crc_simple(text) RETURNS integer
AS '/usr/local/pgsql84/a.out', 'pg_crc_simple'
LANGUAGE C STRICT;
Notese que compile el código en la carpeta /usr/local/pgsql84 y por defecto el 'gcc' nombra al archivo de salida como a.out.
Probemos como funciona!
postgres=# select pg_crc_simple(random()::text); pg_crc_simple_2 ----------------- 1107002784 (1 row)
Aplicación sobre la tabla
Suponemos entonces tenemos una tabla con el campo que queremos hashear y el campo donde guardaremos ese valor.
create table miTablita(nombre text,nombreCrc int);
Ahora inserto los nombres y luego sus CRC:
insert into miTablita(nombre) (select substring(random()::text,3,9) from generate_series(1,100) );
update miTablita set nombreCrc = pg_crc_simple_2(nombre);