Reglas frente triggers

Son muchas las cosas que se hacen utilizando triggers que pueden hacerse tambi�n utilizando el sistema de las reglas de Postgres. Lo que actualmente no se puede implementar a trav�s de reglas son algunos tipos de restricciones (constraints). Es posible situar una regla cualificada que reescriba una query a NOTHING si el valor de la columna no aparece en otra tabla, pero entonces los datos son eliminados silenciosamente, y eso no es una buena idea. Si se necesitan comprobaciones para valores v�lidos, y en el caso de aparecer un valor inv�lido dar un mensaje de error, eso deber� hacerse por ahora con un trigger.

Por otro lado, un trigger que se dispare a partir de una INSERT en una vista puede hacer lo mismo que una regla, situar los datos en cualquier otro sitio y suprimir la inserci�n en una vista. Pero no puede hacer lo mismo en una UPDATE o una DELETE, poruqe no hay datos reales en la relaci�n vista que puedan ser comprobados, y por ello el trigger nunca podr�a ser llamado. S�lo una regla podr�a ayudarnos.

Para los tratamientos que podr�an implementarse de ambas formas, depender� del uso de la base de datos cu�l sea la mejor. Un trigger se dispara para cada fila afectada. Una regla manipula el �rbol de traducci�n o genera uno adicional. De modo que si se manupulan muchas filas en una instrucci�n, una regla ordenando una query adicional usualmente dar�a un mejor resultado que un trigger que se llama para cada fila individual y deber� ejecutar sus operaciones muchas veces.

Por ejemplo: hay dos tablas.

    CREATE TABLE computer (
        hostname        text     -- indexed
	manufacturer    text     -- indexed
    );

    CREATE TABLE software (
        software        text,    -- indexed
        hostname        text     -- indexed
    );
Ambas tablas tienen muchos millares de filas y el �ndice sobre hostname es �nico. La columna hostname contiene el nombre de dominio cualificado completo del ordenador. La regla/trigger deber�a desencadenar el borrado de filas de la tabla software que se refieran a un host borrado. Toda vez que el trigger se llama para cada fila individual borrada de computer, se puede usar la instrucci�n
    DELETE FROM software WHERE hostname = $1;
en un plan preparado y salvado, y pasar el hostname en el par�metro. La regla deber�a ser escrita como
    CREATE RULE computer_del AS ON DELETE TO computer
        DO DELETE FROM software WHERE hostname = OLD.hostname;
Veremos ahora en que se diferencian los dos tipos de delete. En el caso de una
    DELETE FROM computer WHERE hostname = 'mypc.local.net';
La tabla computer se revisa por �ndice (r�pido) y la query lanzada por el trigger tambi�n deber�a ser un barrido de �ndice (r�pido tambi�n). La query extra para la regla ser�a una
    DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
                           AND software.hostname = computer.hostname;
Puesto que se han creado los �ndices apropiados, el optimizador crear� un plan de
    Nestloop
      ->  Index Scan using comp_hostidx on computer
      ->  Index Scan using soft_hostidx on software
De modo que no habr�a mucha diferencia de velocidad entre la implementaci�n del trigger y de la regla. Con la siguiente delete, queremos mostrar borrar los 2000 ordenadores cuyo hostname empieza con 'old'. Hay dos posibles queries para hacer eso. Una es
    DELETE FROM computer WHERE hostname >= 'old'
                           AND hostname <  'ole'
Donde el plan de ejecuci�n para la query de la regla ser�
    Hash Join
      ->  Seq Scan on software
      ->  Hash
	    ->  Index Scan using comp_hostidx on computer
La otra query posible es
    DELETE FROM computer WHERE hostname ~ '^old';
con un plan de ejecuci�n
    Nestloop
      ->  Index Scan using comp_hostidx on computer
      ->  Index Scan using soft_hostidx on software
Esto muestra que el optimizador no comprueba que la cualificaci�n sobre hostname en computer tambi�n deber�a se utilizado para un barrido por �ndice en software donde hay m�ltiples expresiones de cualificaci�n combinadas con AND, que el hace en la versi�n regexp de la query. El trigger ser� invocado una vez para cada una de los 2000 viejos ordenadores que ser�n borrados, lo que dar� como resultado un barrido por �ndice sobre computer y 2000 barridos por �ndice sobre software. La implementaci�n de la regla lo har� con dos queries sobre �ndices. Y depender� del tama�o promedio de la tabla software si la regla ser� m�s r�pida en una situaci�n de barrido secuencial. 2000 ejecuciones de queries sobre el gestor SPI toman su tiempo, incluso si todos los bloques del �ndice se encuentran en la memor�a cach�.

La �ltima query que veremos es

    DELETE FROM computer WHERE manufacurer = 'bim';
De nuevo esto deber�a dar como resultado muchoas filas para borrar de computer. Por ello el trigger disparar� de nuevo muchas queries sobre el ejecutor. Pero el plan de las reglas ser� de nuevo un bucle anidado sobre dos barridos de �ndice. S�lo usando otro �ndice en computer:
    Nestloop
      ->  Index Scan using comp_manufidx on computer
      ->  Index Scan using soft_hostidx on software
dando como resultado de la query de las reglas
    DELETE FROM software WHERE computer.manufacurer = 'bim'
                           AND software.hostname = computer.hostname;
En cualquiera de estos casos, las queries extra del sistema de reglas ser�n m�s o menos independientes del n�mero de filas afectadas en la query.

Otra situaci�n son los casos de UPDATE donde depende del cambio de un atributo si la acci�n deber�a realizarse o no. En la versi�n 6.4 de Postgres, la especificaci�n de atributos para acontencimientos de reglas se ha deshabilitado (y tendr� su regreso en la 6.5, quiz� antes �permanezcan en antena!). De modo que por ahora la �nica forma de crear una regla como en el ejemplo de shoelace_log es hacerlo con una cualficaci�n de la regla. Eso da como resultado una query adicional que se realiza siempre, incluso si el atributo que nos interesa no puede ser cambiado de ninguna forma porque no aparece en la lista objetivo de la query inicial. Cuando se habilite de nuevo, ser� una nueva ventaja del sistema de reglas sobre los triggers. La optimizaci�n de un trigger deber� fallar por definici�n en este caso, porque el hecjo de que su accoi�n solo se har� cuando un atributo espec�fico sea actualizado, est� oculto a su funcionalidad. La definici�n de un trigger s�lo permite especificar el nivel de fila, de modo que si se toca una fila, el trigger ser� llamado a hacer su trabajo. El sistema de reglas lo sabr� mir�ndo la lista objetivo y suprimir� la query adicional por completo si el atributo no se ha tocado. De modo que la regla, cualificada o no, s�lo har� sus barridos si tiene algo que hacer.

Las reglas s�lo ser�n significativamente m�s lentas que los triggers si sus acciones dan como resultado joins grandes y mal cualificadas, una situaci�n en la que falla el optimizador. Tenemos un gran martillo. Utilizar un gran martillo sin cuidado puede causar un gran da�o, pero dar el toque correcto, puede hundir cualquier clavo hasta la cabeza.