Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Qual é a melhor maneira de atualizar uma tabela de rollup sob carga?


A maneira como fiz isso em alguns projetos é usar duas cópias da tabela em esquemas diferentes. Então 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

Agora crie um procedimento armazenado que trunque e preencha novamente a tabela falsa e, em uma transação, mova os objetos entre os 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

Este é provavelmente o menor período de tempo que você pode fazer com que os usuários esperem que os novos dados sejam atualizados e sem interrompê-los no meio de uma leitura. (Existem muitos problemas associados ao NOLOCK que o tornam uma alternativa menos desejável, embora reconhecidamente, seja fácil de codificar.) Para brevidade/claridade, deixei de fora o tratamento de erros etc. scripts para sincronizar seus bancos de dados, certifique-se de nomear restrições, índices etc. o mesmo em ambas as tabelas, caso contrário você ficará fora de sincronia metade do tempo. Ao final do procedimento você pode TRUNCAR a nova tabela fake.MySummary, mas se tiver espaço, gosto de deixar os dados lá para sempre poder comparar com a versão anterior.

Antes do SQL Server 2005, eu usava sp_rename dentro da transação para realizar exatamente a mesma coisa, no entanto, como faço isso em um trabalho, fiquei feliz em alternar para esquemas, porque quando o fiz, o aviso non-suppress-able de sp_rename parou de preencher meus logs de histórico do SQL Server Agent.