AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 298449
Accepted
Dai
Dai
Asked: 2021-08-24 13:31:53 +0800 CST2021-08-24 13:31:53 +0800 CST 2021-08-24 13:31:53 +0800 CST

Como posso suprimir ou desabilitar a inserção de histórico de tabela temporal para uma única instrução ou transação?

  • 772

Eu tenho uma tabela que armazena informações do cliente (seu material de CRM padrão do pântano):

CREATE TABLE dbo.Customers (
    TenantId    int            NOT NULL,
    CustomerId  int            NOT NULL,
    
    FirstName   nvarchar(50)   NOT NULL DEFAULT '',
    LastName    nvarchar(50)   NOT NULL DEFAULT '',
    CompanyName nvarchar(50)   NOT NULL DEFAULT '',

    Notes       nvarchar(4000) NOT NULL DEFAULT ''
)

Esta tabela foi recentemente convertida em uma tabela temporal do SQL Server:

ALTER TABLE dbo.Customers
    ADD COLUMN
        SysStart datetime2(7) GENERATED ALWAYS AS ROW START NOT NULL,
        SysEnd   datetime2(7) GENERATED ALWAYS AS ROW END   NOT NULL;

GO

ALTER TABLE dbo.Customers WITH (
    PERIOD FOR SYSTEM_TIME ( SysStart, SysEnd ),
    SYSTEM_VERSIONING = ON ( HISTORY_TABLE = dbo.Customers_History )
)

Desde que isso aconteceu, um problema surgiu: o formulário voltado para o usuário que os usuários editam os detalhes do cliente salva automaticamente o conteúdo do formulário 2 segundos após o último pressionamento de tecla, e cada salvamento resulta em uma UPDATEinstrução com quantidades de dados cada vez maiores - e assim SQL Server está constantemente adicionando novas linhas à Customers_Historytabela, com 2 segundos de intervalo, o que resulta em linhas com poucas informações e spam.

Então é isso que eu vejo quando faço um SELECT * FROM dbo.Customers_History WHERE CustomerId = 123, por exemplo:

insira a descrição da imagem aqui

Eu estava pensando que o código do lado do servidor que lida com os envios de salvamento automático poderia verificar se o estado do formulário de entrada é uma alteração incremental e, em caso afirmativo, UPDATEa dbo.Customerstabela sem adicionar nenhuma linha à Customers_Historytabela.

Até agora, a única maneira que vejo para fazer isso é definindoSYSTEM_VERSIONING = OFF dentro de uma transação, no entanto, tenho algumas dúvidas antes de realmente implementar isso ...

  1. Embora a documentação diga (até recomende) a execução ALTER TABLE dbo.Customers SET (SYSTEM_VERSIONING = OFF);dentro de uma transação, ela não diz como isso afetaria outros usuários e conexões simultâneos . Afinal, esta é uma instrução DML, e as instruções DML têm comportamento inconsistente (hah!) com isolamento.

  2. Iniciar e concluir uma transação em um PROCEDURElote armazenado ou SQL é uma coisa - mas determinar se um UPDATEé realmente incremental ou não pode exigir alguma lógica de código de aplicativo personalizado, o que significa ter que iniciar e confirmar a transação a partir do código de aplicativo, o que parece uma má ideia por causa das milhares de coisas que agora podem dar errado , sem falar nos problemas de desempenho (neste caso, a latência da rede do servidor de aplicativos para o servidor de banco de dados deve ser inferior a 1 ms, mas isso ainda afetará a escalabilidade ).


Supondo que eu possa fazer isso em um PROCEDURE, este código abaixo está correto e ele será dimensionado?

CREATE PROCEDURE dbo.UpdateSingleCustomerRow(
    @tenantId    int,
    @customerId  int,
    @firstName   nvarchar(50),
    @lastName    nvarchar(50),
    @companyName nvarchar(50),
    @notes       nvarchar(4000)
)

BEGIN TRY

    BEGIN TRANSACTION editCustomerTxn;

    SET XACT_ABORT ON;

    -- Is it an incremental change?
    DECLARE @isIncremental bit = 0;

    IF EXISTS( SELECT 1 FROM dbo.Customers WHERE
        CustomerId = @customerId
        AND
        TenantId = @tenantId
        AND
        CHARINDEX( FirstName, @firstName ) > 0
        AND
        CHARINDEX( LastName, @lastName ) > 0
        AND
        CHARINDEX( CompanyName, @companyName ) > 0
        AND
        CHARINDEX( Notes, @notes ) > 0
    )
    BEGIN
        SET @isIncremental = 1;
    END

    -----------------------

    IF @isIncremental = 1
    BEGIN
        ALTER TABLE dbo.Customers SET ( SYSTEM_VERSIONING = OFF );
    END

    UPDATE
        dbo.Customers
    SET
        FirstName   = @firstName,
        LastName    = @lastName,
        CompanyName = @companyName,
        Notes       = @notes
    WHERE
        CustomerId = @customerId
        AND
        TenantId = @tenantId;
    
    IF @isIncremental = 1
    BEGIN
        ALTER TABLE dbo.Customers SET (
            SYSTEM_VERSIONING = ON(
                HISTORY_TABLE = dbo.Customers_History
            )
        );
    END
    
    COMMIT TRANSACTION editCustomerTxn;

    RETURN 0;

END TRY
BEGIN CATCH
    
    IF @@TRANCOUNT > 0
    BEGIN
        ROLLBACK TRANSACTION editCustomerTxn;
    END
    
    RETURN 1;

END CATCH

... mas isso não parece certo para mim - porque isso é basicamente a mesma coisa que hackear restrições adiáveis ​​com ALTER TABLE dbo.Customers NOCHECK CONSTRAINT ALL.

sql-server azure-sql-database
  • 2 2 respostas
  • 256 Views

2 respostas

  • Voted
  1. AMtwo
    2021-08-24T16:50:29+08:002021-08-24T16:50:29+08:00

    Isso soa como um caso em que o comportamento do aplicativo e o recurso de banco de dados simplesmente não combinam muito bem. Você pode alterar o comportamento do seu aplicativo para que os salvamentos incrementais não sejam feitos nessa tabela de forma tão agressiva (talvez o armazenamento em cache salve mais lentamente em outro lugar) ou para não usar tabelas temporais.

    Se você não pode alterar o comportamento do aplicativo, parece que esta é uma oportunidade de usar um gatilho em vez de uma tabela temporal. O gatilho pode ter lógica para lidar com "salvamentos intermediários" para que eles obedeçam um período de carência para limitar os salvamentos frequentes.

    O Stack Overflow e a Stack Exchange Network têm um período de carência de 5 minutos para edição .

    Para evitar que uma série de pequenas edições apareçam no histórico de revisões, um único usuário que edita uma postagem recebe um período de carência de 5 minutos ... Durante esse período, todas as edições adicionais feitas são recolhidas na mesma edição no histórico de revisões, exibindo apenas o resultado final de todas as edições dentro desse período de 5 minutos.

    Independentemente de você implementar o período de carência para o histórico de edições no nível do aplicativo ou no nível do banco de dados, definitivamente haverá um pouco de codificação de sua parte, pois não há recurso de banco de dados para fazer isso automaticamente para você.

    • 5
  2. Best Answer
    David Browne - Microsoft
    2021-08-24T15:41:13+08:002021-08-24T15:41:13+08:00

    executando ALTER TABLE dbo.Customers SET (SYSTEM_VERSIONING = OFF); dentro de uma transação, não diz como isso afetaria outros usuários e conexões simultâneos.

    ALTER TABLE sempre requer um bloqueio de esquema exclusivo (Sch-M). Portanto, nenhuma outra sessão pode ler, atualizar ou alterar a tabela até que a transação seja confirmada ou revertida.

    este código abaixo está correto e será dimensionado?

    Não vai escalar.

    Então

    formulário voltado para o usuário que os usuários editam os detalhes do cliente salva automaticamente o conteúdo do formulário 2 segundos após o último pressionamento de tecla, e cada salvamento resulta em uma instrução UPDATE

    mude isso ou viva com a tabela de histórico detalhada. Você sempre pode executar um trabalho em lote para excluir algumas das linhas do histórico (depois de desativar SYSTEM_VERSIONING em uma transação :)).

    • 4

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve