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.