2010-12-02 10 views
6

actualización:¿Cuál es la mejor opción en delete-insert vs if-update else-insert?

Mi mal ... tengo una clave principal en esos tables..I significaba no más lejos de indexación actualmente en las tablas . Puede que lo tengamos en el futuro después de ver el rendimiento y, dado que tenemos demasiados filtros en los datos en recuperando datos, no mostró mucha mejoría en la indexación la última vez que ejecutamos la base de datos .

Tengo 4 mesas grandes en millones de registros. Ahora hay un procedimiento almacenado que se llama con frecuencia y actualiza estas tablas. Aquí está el escenario:

Ahora, si la entrada existe para hoy, necesito actualizarla hoy y, si la entrada no está para el usuario, debo continuar e insertar una entrada para el usuario. Ahora bien, hay dos maneras de ir sobre la realización de éstos, ya que hay un solo proc que hace esto -

primera forma -

IF EXISTS(TABLE1) 
--UPDATE where condn 
ELSE 
--INSERT 
IF EXISTS(TABLE2) 
--UPDATE where condn 
ELSE 
--INSERT 
IF EXISTS(TABLE3) 
--UPDATE where condn 
ELSE 
--INSERT 
IF EXISTS(TABLE4) 
--UPDATE where condn 
ELSE 
--INSERT 

segunda manera -

DELETE from TABLE1 where condn 
DELETE from TABLE2 where condn 
DELETE from TABLE3 where condn 
DELETE from TABLE4 where condn 

INSERT TABLE1 ENTRY 
INSERT TABLE2 ENTRY 
INSERT TABLE3 ENTRY 
INSERT TABLE4 ENTRY 

ahora la segunda manera miradas más simple, pero podría llevar más tiempo ... No estoy seguro de qué manera es la mejor aquí. ¿Alguien puede por favor ayudarme o guiarme aquí ... gracias!

+1

Como MERGE no está disponible en SQL2005 (por ejemplo para aquellos que lo comentaron), preferiría la primera manera. El peor escenario posible para una segunda forma podría ser que tiene una identidad como un índice agrupado, lo que da como resultado al menos dos operaciones de escritura para cada cambio. –

+1

OP dice: 'No hay indexación actualmente en las tablas. Podríamos tenerlo en el futuro "y' 4 tablas enormes sobre millones de registros'. Tenga en cuenta que una clave principal le da un índice. Si no tiene PK, entonces yo digo: ** ¡el futuro es ahora! ** en nombre del rendimiento ¡POR FAVOR agregue un índice que le ayude a su 'condición de lugar '! –

+0

¡He actualizado mi pregunta! – Vishal

Respuesta

2

El si-existe-entonces-update-cosa-inserte enfoque puede ser más código que delete-insert, pero (dependiendo de cuántos y qué tipo de índices se definen en las tablas) es mucho menos trabajo para el servidor.

  • Una operación DELETE o INSERT requiere que se modifique cada índice, punto.
  • Una operación de ACTUALIZACIÓN solo requiere que estos índices se modifiquen cuyos campos se han actualizado en esta instancia.

Así que a menos que modifique cada campo indexado del registro con sus actualizaciones, el enfoque más largo es el más eficiente.


EDIT: Su actualización pregunta dice que en la actualidad no tiene ningún índice, aparte de la clave principal (que supongo es una clave agrupada). Así que en la comparación:

Cuando la fila ya existe, es 1 índice agrupado buscan (suponiendo que encuentre registros por su PK) y:

  • delete-inserte: 4 operaciones de escritura (eliminar fila, eliminar fila de índice PK, insertar fila, insertar fila de índice PK)
  • check-update/insert: 1 operación de escritura (actualización de fila)

Cuando no existe todavía la fila, es 1 índice agrupado buscar y:

  • eliminar a insertar: 2 operaciones de escritura (fila de inserción, insertar fila de índice PK)
  • facturación actualización/insertar: 2 operaciones de escritura (fila de inserción, inserte índice PK fila)

existen las más índices, peor será eliminar/insertar realizar para las filas que ya existen. Además, puede causar que los índices no agrupados se fragmenten innecesariamente debido a operaciones de escritura evitables.

1

probar esto:

UPDATE TABLE1 where condn 
IF @@ROWCOUNT=0 
    INSERT TABLE1.... 

UPDATE TABLE2 where condn 
IF @@ROWCOUNT=0 
    INSERT TABLE2.... 

UPDATE TABLE3 where condn 
IF @@ROWCOUNT=0 
    INSERT TABLE3.... 

UPDATE TABLE4 where condn 
IF @@ROWCOUNT=0 
    INSERT TABLE4.... 

no estoy seguro si esto funcionaría (pregunta no proporciona suficiente información):

UPDATE TABLE1 where condn 
IF @@ROWCOUNT=0 
BEGIN 
    INSERT TABLE1.... 
    INSERT TABLE2.... 
    INSERT TABLE3.... 
    INSERT TABLE4.... 
END 
ELSE 
BEGIN 
    UPDATE TABLE2 where condn 
    UPDATE TABLE3 where condn 
    UPDATE TABLE4 where condn 
END 
6

que tengan previsto en su mayoría inserciones, prueba este

... 
BEGIN TRY 
    INSERT table1 
END TRY 
BEGIN CATCH 
    IF ERROR_NUMBER = 2627 
     UPDATE table1 
    ELSE 
     --process real error 
END CATCH 
... 

Más actualizaciones ...

... 
BEGIN TRY 
    UPDATE table1 ... WHERE ... 
    IF @@ROWCOUNT = 0 
     INSERT Table1 
END TRY 
BEGIN CATCH 
    --optional. if someone manages to insert before here, do we update it? or just ignore it? 
    IF ERROR_NUMBER = 2627 
     UPDATE table1 
    ELSE 
     --process real error 
END CATCH 
... 

EXISTS no es lo suficientemente concurrente bajo altas cargas. Si va a escanear la tabla con EXISTS, también puede intentar INSERTAR de todos modos.

Otras respuestas: One, Two, Three

Editar: Yo llamo a esto el patrón JFDI ...

+0

¡Bonito nombre de patrón! –

+0

Recibo este error al insertar primero :("La transacción actual no puede confirmarse y no puede admitir operaciones que escriben en el archivo de registro. Revertir la transacción. La declaración ha finalizado." – andrecarlucci

+0

@andrecarlucci usted puede tener SET XACT_ABORT ENCENDIDO o un disparador que "condena" la transacción. Debería usar MERGE en versiones posteriores de SQL – gbn

Cuestiones relacionadas