sql >> Base de Datos >  >> RDS >> Sqlserver

¿Cuál es la mejor manera de actualizar una tabla acumulativa bajo carga?

La forma en que lo he hecho en algunos proyectos es usar dos copias de la tabla en diferentes esquemas. Así que algo como:

CREATE SCHEMA fake WITH AUTHORIZATION dbo;
CREATE SCHEMA standby WITH AUTHORIZATION dbo;
GO

CREATE TABLE dbo.mySummary(<...columns...>);

CREATE TABLE fake.mySummary(<...columns...>);
GO

Ahora cree un procedimiento almacenado que trunque y vuelva a llenar la tabla falsa, luego, en una transacción, mueva los objetos entre esquemas.

CREATE PROCEDURE dbo.SwapInSummary
AS
BEGIN
    SET NOCOUNT ON;

    TRUNCATE TABLE fake.mySummary;

    INSERT fake.mySummary(<...columns...>)
        SELECT <expensive query>;

    BEGIN TRANSACTION;
        ALTER SCHEMA standby TRANSFER dbo.mySummary;
        ALTER SCHEMA dbo     TRANSFER fake.mySummary;
        ALTER SCHEMA fake    TRANSFER standby.mySummary;
    COMMIT TRANSACTION;
END
GO

Esta es probablemente la menor cantidad de tiempo que puede hacer que los usuarios esperen a que se actualicen los nuevos datos y sin interrumpirlos en medio de una lectura. (Hay muchos problemas asociados con NOLOCK que lo convierten en una alternativa menos deseable, aunque es cierto que es fácil de codificar). Por brevedad/claridad, he omitido el manejo de errores, etc., y también debo señalar que si usa scripts para sincronizar sus bases de datos, asegúrese de nombrar las restricciones, los índices, etc. de la misma manera en ambas tablas; de lo contrario, no estará sincronizado la mitad del tiempo. Al final del procedimiento, puede TRUNCAR la nueva tabla fake.MySummary, pero si tiene espacio, me gusta dejar los datos allí para poder compararlos siempre con la versión anterior.

Antes de SQL Server 2005, usaba sp_rename dentro de la transacción para lograr exactamente lo mismo; sin embargo, dado que hago esto en un trabajo, me alegró cambiar a esquemas, porque cuando lo hice, la advertencia de sp_rename que no se puede suprimir dejó de llenarse. actualizar mis registros de historial del Agente SQL Server.