Creando Hash en tablas para mejorar rendimiento

From PostgreSQL wiki
Jump to navigationJump to search

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);