Comparando Merge vs. SP

Comparando Merge con Store Procedures individuales

La instrucción Merge realiza instrucciones de inserción de registros, actualización o eliminación de registros en una tabla de destino en la misma base de datos o en otra base de datos según los resultados de combinar los registros con una tabla de origen, esta tabla origen puede ser una consulta Select.

Merge puede ser usado de varias formas, en este artículo se hará la comparación de usar Merge que haga el trabajo de inserción y de modificación en el mismo procedimiento con el uso de procedimientos individuales para cada operación.

Para más información ver:

Merge en SQL Server
Usando Merge con Select
Merge en Graph Tables
OutPut en Merge
Procedimientos almacenados
Variables en SQL Server
Insertar registros
Actualización de registros

Ejercicios

Usando la base de datos Northwind

use Northwind
go

Ejercicio 1

En este primer ejercicio se crea un procedimiento almacenado que evalua la existencia de un Cliente, si el cliente existe se van a actualizar sus datos y si no existe se va a insertar un nuevo cliente. En este procedimiento se usa la instrucción Merge con un Select.

Create or alter procedure spClientesActualizaInsertaMerge
	(	
		@Codigo nchar(5),
		@Nombre nvarchar(40),
		@Contacto nvarchar(30),
		@Cargo nvarchar(30),
		@Direccion nvarchar(60),
		@Ciudad nvarchar(15),
		@Region nvarchar(15),
		@CodigoPostal nvarchar(10),
		@Pais nvarchar(15),
		@Fono nvarchar(24),
		@Fax nvarchar(24)
	)
As
	MERGE dbo.Customers As ClientesDestino
			USING
			(
			SELECT @Codigo, @Nombre, @Contacto, @Cargo, @Direccion,
				   @Ciudad, @Region, @CodigoPostal, @Pais, @Fono, @Fax) 
				   As ClientesOrigen 
					([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], 
					[City], [Region], [PostalCode], [Country], [Phone], [Fax])
		ON ClientesDestino.CustomerId = ClientesOrigen.CustomerId
	WHEN MATCHED then  -- Cliente encontrado
	  UPDATE 
		SET [CustomerID]=ClientesOrigen.[CustomerID],
			[CompanyName]=ClientesOrigen.[CompanyName], 
			[ContactName]=ClientesOrigen.[ContactName],
			[ContactTitle]=ClientesOrigen.[ContactTitle],
			[Address]=ClientesOrigen.[Address], 
			[City]=ClientesOrigen.[City],
			[Region]=ClientesOrigen.[Region], 
			[PostalCode]=ClientesOrigen.[PostalCode],
			[Country]=ClientesOrigen.[Country],
			[Phone]=ClientesOrigen.[Phone],
			[Fax]=ClientesOrigen.[Fax]
	WHEN NOT MATCHED THEN -- Cliente no encontrado
			INSERT VALUES
			 (@Codigo, @Nombre, @Contacto, @Cargo, @Direccion,
				   @Ciudad, @Region, @CodigoPostal, @Pais, @Fono, @Fax);
go

Listado de los clientes, se puede ver que el cliente con el que se va a ejecutar el SP no existe. Note que el cliente con ID BBC45 no existe.

Select * from dbo.customers
go
El resultado se muestra en la siguiente imagen

Ejecutar el SP con un nuevo cliente.
Los datos del nuevo cliente son:
Codigo = 'BBC45'
Nombre = 'Black Software Ingenieros'
Contacto = 'FERNANDO LUQUE SANCHEZ'
Cargo = 'Gerente de Procesos'
Direccion = 'Av. Arequipa 9494'
Ciudad = 'Lima'
Region = 'CE'
CodigoPostal = '11580'
Pais = 'Perú'
Fono = '949483333'
Fax = '052-525258'

Ejecutando el procedimiento almacenado.

Execute spClientesActualizaInsertaMerge 
		@Codigo  = 'BBC45',
		@Nombre = 'Black Software Ingenieros',
		@Contacto = 'FERNANDO LUQUE SANCHEZ',
		@Cargo = 'Gerente de Procesos',
		@Direccion = 'Av. Arequipa 9494',
		@Ciudad = 'Lima',
		@Region = 'CE',
		@CodigoPostal = '11580',
		@Pais = 'Perú' ,
		@Fono = '949483333',
		@Fax  = '052-525258'
go

Listado de los clientes
select * from dbo.customers
go
El resultado se muestra en la siguiente imagen

Cliente con ID BBC45 insertado

Ejecutamos el SP con el mismo código del cliente pero con algunos datos cambiados.

Execute spClientesActualizaInsertaMerge 
		@Codigo  = 'BBC45',
		@Nombre = 'Black Software Apps',
		@Contacto = 'FERNANDO LUQUE SANCHEZ',
		@Cargo = 'Gerente General',
		@Direccion = 'Av. Guardia Civil 189',
		@Ciudad = 'Lima',
		@Region = 'CE',
		@CodigoPostal = '11900',
		@Pais = 'Perú' ,
		@Fono = '949363636',
		@Fax  = '052-115511'
go

Listado de los clientes
select * from dbo.customers
go
El resultado se muestra en la siguiente imagen
Note que se han actualizado el nombre del cliente, el cargo, la dirección, el código postal, el teléfono y el fax.

Ejercicio 2

Usando procedimientos almacenados individuales, uno para la inserción y otro para la actualización de datos, luego estos procedimientos se va a comparar con el use del procedimiento del ejercicio 1 para ver cual es mas eficiente.

Procedimiento para insertar un registro.

Create or alter procedure spClientesInserta
	(	
		@Codigo nchar(5),
		@Nombre nvarchar(40),
		@Contacto nvarchar(30),
		@Cargo nvarchar(30),
		@Direccion nvarchar(60),
		@Ciudad nvarchar(15),
		@Region nvarchar(15),
		@CodigoPostal nvarchar(10),
		@Pais nvarchar(15),
		@Fono nvarchar(24),
		@Fax nvarchar(24)
	)
As
	INSERT into dbo.Customers 
		  ([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address], 
		    [City], [Region], [PostalCode], [Country], [Phone], [Fax])
			VALUES
		 (@Codigo, @Nombre, @Contacto, @Cargo, @Direccion,
		   @Ciudad, @Region, @CodigoPostal, @Pais, @Fono, @Fax);
go

Ejecutando el procedimiento almacenado

Execute spClientesInserta
@Codigo = 'ILC24',
@Nombre = 'ACW Contratistas',
@Contacto = 'Ingrid Llanos',
@Cargo = 'CEO',
@Direccion = 'Av. Los Laureles 4995',
@Ciudad = 'Lima',
@Region = 'CE',
@CodigoPostal = '52525',
@Pais = 'Perú' ,
@Fono = '969694947',
@Fax = '052-365263'
go

Procedimiento para modificar los datos de un registro.

Create or alter procedure spClientesActualiza
	(	
		@Codigo nchar(5),
		@Nombre nvarchar(40),
		@Contacto nvarchar(30),
		@Cargo nvarchar(30),
		@Direccion nvarchar(60),
		@Ciudad nvarchar(15),
		@Region nvarchar(15),
		@CodigoPostal nvarchar(10),
		@Pais nvarchar(15),
		@Fono nvarchar(24),
		@Fax nvarchar(24)
	)
As
	 UPDATE  dbo.Customers
		SET [CompanyName]=@Nombre, 
			[ContactName]=@Contacto,
			[ContactTitle]=@Cargo,
			[Address]=@Direccion, 
			[City]=@Ciudad,
			[Region]=@Region, 
			[PostalCode]=@CodigoPostal,
			[Country]=@Pais,
			[Phone]=@Fono,
			[Fax]=@Fax
			where [CustomerID]=@Codigo
go

Ejecutando el procedimiento almacenado para actualizar los datos de un cliente.

Execute spClientesActualiza
@Codigo = 'ILC24',
@Nombre = 'ACW Contratistas',
@Contacto = 'Ing. Esmeralda Sandoval Wong',
@Cargo = 'Administrador',
@Direccion = 'Av. San Pablo 4995',
@Ciudad = 'Lima',
@Region = 'CE',
@CodigoPostal = '45154',
@Pais = 'Perú' ,
@Fono = '969694947',
@Fax = '052-365263'
go

Listado de clientes, se puede ver el cliente nuevo.
select * from dbo.customers
go
El resultado se muestra en la siguiente imagen

Comparando los Costos de ejecución de cada opción

Para mostrar el costo del uso de cada opción se insertará el mismo registro, obviamente después de usar Merge se procede a borrar el registro para ejecutar el SP que inserta el registro, mostrando para cada caso el tiempo de ejecución usando el Plan de ejecución estimado.

Insertar un registro con Merge

Execute spClientesActualizaInsertaMerge
@Codigo = 'ABC96',
@Nombre = 'ThunderApps Co.',
@Contacto = 'Leo Campos Guevara',
@Cargo = 'Gerente Comercial',
@Direccion = 'Av. Ciro Alegría 575',
@Ciudad = 'Trujillo',
@Region = 'CE',
@CodigoPostal = '54858',
@Pais = 'Perú' ,
@Fono = '949422112',
@Fax = '052-36362'
go

El Plan de ejecución estimado con el costo se muestra en la imagen siguiente

Plan de ejecución estimado de la inserción de un cliente con el SP que usa Merge

Note que el costo es: 0.153338

Borramos el registro para insertarlo con el SP individual.
delete dbo.Customers where CustomerID = 'ABC96'
go

Insertar el registro con el SP individual de inserción creado llamado spClientesInserta

Execute spClientesInserta
@Codigo = 'ABC96',
@Nombre = 'ThunderApps Co.',
@Contacto = 'Leo Campos Guevara',
@Cargo = 'Gerente Comercial',
@Direccion = 'Av. Ciro Alegría 575',
@Ciudad = 'Trujillo',
@Region = 'CE',
@CodigoPostal = '54858',
@Pais = 'Perú' ,
@Fono = '949422112',
@Fax = '052-36362'
go

El Plan de ejecución estimado con el costo se muestra en la imagen siguiente

Note que el costo es: 0.0500062

Comparando:
Costo usando SP con Merge para insertar: 0.1533380
Costo usando SP individual al insertar: 0.0500062
Definitivamente la mejor opción es trabajar con SP sin Merge para la acción de insertar.

Actualizar los datos del cliente

Usando el SP con Merge llamado spClientesActualizaInsertaMerge, el cliente con código ABC96 si existe.

Execute spClientesActualizaInsertaMerge
@Codigo = 'ABC96',
@Nombre = 'ThunderApps Co.',
@Contacto = 'Fernando León Llanos',
@Cargo = 'Gerente de Marketing',
@Direccion = 'Av. Dinamarca 22441',
@Ciudad = 'Trujillo',
@Region = 'CE',
@CodigoPostal = '54858',
@Pais = 'Perú' ,
@Fono = '94959697',
@Fax = '052-12128'
go
El Plan de ejecución estimado con el costo se muestra en la imagen siguiente

Plan de ejecución estimado de la modificación de los datos de un cliente con el SP que usa Merge

Note que el costo es: 0.153338

Actualizar el registro usando el SP llamado spClientesActualiza

Execute spClientesActualiza
@Codigo = 'ABC96',
@Nombre = 'ThunderApps Co.',
@Contacto = 'Fernando León Sánchez',
@Cargo = 'Gerente de Finanzas',
@Direccion = 'Av. Mónaco 46655',
@Ciudad = 'Trujillo',
@Region = 'CE',
@CodigoPostal = '11300',
@Pais = 'Perú' ,
@Fono = '949798953',
@Fax = '052-36363'
go
El Plan de ejecución estimado con el costo se muestra en la imagen siguiente

Note que el costo es: 0.0532883

Comparando la opción de modificación:
Costo usando SP con Merge para insertar: 0.1533380
Costo usando SP individual al insertar: 0.0532883
Definitivamente la mejor opción es trabajar con SP sin Merge para la acción de modificar.