Rendimiento de un disparador vs procedimiento almacenado en MySQL


11

Una publicación aquí en DBA. StackExchange ( ¿Cuáles son las mejores prácticas para que los desencadenantes mantengan un número de revisión en los registros? ) Ha generado una pregunta interesante (al menos, interesante para mí) con respecto al rendimiento en MySQL.

El contexto es que queremos insertar un registro en una tabla para cada fila que se actualiza. Antes de actualizar la fila, queremos almacenar un valor anterior y luego incrementar una de las columnas (una columna de "versión").

Si hacemos esto dentro de un disparador, funciona bien. Para MySQL, los desencadenantes son fila por fila , por lo que sería una solución fácil. Seleccione los datos actualmente en la tabla, insértelos en la tabla de registro y actualice la columna "versión" en los nuevos datos.

Sin embargo, es posible mover esta lógica a un procedimiento almacenado. Si hace eso, está realizando la inserción y luego incrementa la columna "versión" en la tabla. Todo se establecería en base.

Entonces, cuando se trata de realizar esta inserción, ¿sería más rentable usar el enfoque de procedimiento almacenado basado en conjuntos o un enfoque basado en disparador?

Esta pregunta es para MySQL (ya que tiene disparadores de fila por fila), aunque podría aplicarse a otros DBMS de disparador de fila por fila.


1
Una cosa a tener en cuenta con respecto a llevar la lógica de versiones a un procedimiento almacenado: ¿qué tan jodido serás cuando alguien, de alguna manera, escriba directamente en la tabla sin pasar por tu mecanismo de auditoría?
billinkc

Estoy de acuerdo. Pero en el otro extremo de la escala, tal vez desee omitir intencionalmente este registro en ciertas circunstancias. Por supuesto, esa es una pregunta completamente diferente . Realmente tengo curiosidad por las implicaciones de rendimiento.
Richard

Respuestas:


7

En aras de la simplicidad, los disparadores son el camino a seguir para implementar cualquier tipo de seguimiento de los cambios en la base de datos. Sin embargo, debe ser consciente de lo que sucede debajo del capó cuando utiliza disparadores.

De acuerdo con la Programación de procedimientos almacenados de MySQL , la página 256 debajo del encabezado "Trigger Overhead" dice lo siguiente:

Es importante recordar que, por necesidad, los desencadenantes agregan sobrecarga a la declaración DML a la que se aplican. la cantidad real de sobrecarga dependerá de la naturaleza del activador, pero --- como todos los activadores de MySQL se ejecutan PARA CADA FILA --- la sobrecarga puede acumularse rápidamente para las declaraciones que procesan grandes cantidades de filas. Por lo tanto, debe evitar colocar declaraciones SQL costosas o código de procedimiento en activadores.

En las páginas 529-531 se ofrece una explicación ampliada de la sobrecarga del activador. El punto final de esa sección establece lo siguiente:

La lección aquí es esta: dado que el código de activación se ejecutará una vez por cada fila afectada por una instrucción DML, el activador puede convertirse fácilmente en el factor más significativo en el rendimiento de DML. El código dentro del cuerpo del desencadenador debe ser lo más ligero posible y, en particular, cualquier declaración SQL en el desencadenador debe estar respaldada por índices siempre que sea posible.

No mencionado en el libro es otro factor cuando se utilizan disparadores: cuando se trata del registro de auditoría, tenga en cuenta en qué registra los datos. Digo esto porque si elige iniciar sesión en una tabla MyISAM, cada INSERT en una tabla MyISAM produce un bloqueo completo de la tabla durante el INSERT. Esto puede convertirse en un serio cuello de botella en un entorno de alto tráfico y alta transacción. Además, si el desencadenante está en contra de una tabla InnoDB y registra los cambios en MyISAM desde dentro del desencadenante, esto deshabilitará secretamente el cumplimiento de ACID (es decir, reducirá las transacciones de bloque al comportamiento de confirmación automática), que no se puede revertir.

Al usar disparadores en tablas InnoDB y registrar cambios

  • La tabla en la que inicia sesión también es InnoDB
  • Tienes la confirmación automática desactivada
  • Configura INICIAR TRANSACCIÓN ... COMPROMETE / ROLLBACK bloquea completamente

De esta manera, los registros de auditoría pueden beneficiarse de COMMIT / ROLLBACK como lo harían las tablas principales.

Con respecto al uso de procedimientos almacenados, debería llamar minuciosamente el procedimiento almacenado en cada punto de DML contra la tabla que se está rastreando. Uno podría fácilmente perderse los cambios de registro frente a decenas de miles de líneas de código de aplicación. Colocar dicho código en un disparador elimina la búsqueda de todas esas declaraciones DML.

CONSIDERACIÓN

Dependiendo de lo complejo que sea el desencadenante, aún puede ser un cuello de botella. Si desea reducir los cuellos de botella en el registro de auditoría, hay algo que puede hacer. Sin embargo, requerirá un pequeño cambio de infraestructura.

Usando hardware básico, cree dos servidores DB más

Esto servirá para reducir la escritura de E / S en la base de datos principal (MD) debido al registro de auditoría. Así es como puedes lograrlo:

Paso 01) Active el registro binario en la base de datos principal.

Paso 02) Con un servidor económico, configure MySQL (misma versión que MD) con el registro binario habilitado. Esto será DM. Configurar la replicación de MD a DM.

Paso 03) Usando un segundo servidor económico, configure MySQL (la misma versión que MD) con el registro binario deshabilitado. Configure cada tabla de auditoría para usar --replicate-do-table . Esto será AU. Configurar la replicación de DM a AU.

Paso 04) mysqldump las estructuras de la tabla de MD y cargarlo en DM y AU.

Paso 05) Convierta todas las tablas de auditoría en MD para usar el motor de almacenamiento BLACKHOLE

Paso 06) Convierta todas las tablas en DM y AU para usar el motor de almacenamiento BLACKHOLE

Paso 07) Convierta todas las tablas de auditoría en AU para usar el motor de almacenamiento MyISAM

Cuando termine

  • DM replicará desde MD y grabará cosas solo en su registro binario
  • Con el filtro --replicate-do-table en todas las tablas de auditoría, AU se replicará desde DM

Lo que esto hace es almacenar información de auditoría en un servidor de base de datos separado y también reducir cualquier degradación de E / S de escritura que normalmente tendría MD.


Respuesta tremenda +++ 1
b_dubb

1

Aquí hay un enfoque para realizar esta actualización en masa.

Para este ejemplo

  • la tabla_A tiene un ID DE CLAVE PRIMARIA
  • Crea una tabla llamada table_A_Keys2Update con solo ID como PRIMARY KEY
  • Rellene table_A_Keys2Update con identificadores de table_A que sabe que deben actualizarse

Para crear table_A_Keys2Update haga lo siguiente:

CREATE TABLE table_A_Keys2Update SELECT id FROM table_A;
ALTER TABLE table_A_Keys2Update ADD PRIMARY KEY (id);

Después de completar table_A_Keys2Update con los identificadores cuyo número de revisión debe incrementarse, realice la siguiente UPDATE JOIN para incrementar el número de revisión de todas las filas cuyo id está en table_A y table_A_Keys2Update:

UPDATE table_A A INNER JOIN table_A_Keys2Update B USING (id)
SET A.revision = A.revision + 1;

Esta consulta de una línea puede reemplazar un disparador y un procedimiento almacenado.

Opcionalmente, puede colocar esta consulta en un procedimiento almacenado y llamarla si así lo desea.


Es realmente el inserto lo que me interesa. Si INSERTA EN la auditoría, SELECCIONE <lo que sea> DE <primaria_tabla> DONDE <parámetros del procedimiento almacenado> podría hacer la inserción en masa. En el desencadenador, simplemente INSERTARÍA EN los VALORES de auditoría <datos de la fila actualizada> . Entonces, ¿la inserción de una sola fila fila por fila sería más rápida que la inserción masiva?
Richard

En aras de la simplicidad, el desencadenante sería mucho mejor 1) siempre que la tabla_primaria nunca experimente inserciones masivas en medio de las horas pico, 2) la información de auditoría debe leerse a pedido en cualquier momento, y 3) su sitio tiene poco tráfico
RolandoMySQLDBA
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.