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 / 169180
Accepted
Alexei
Alexei
Asked: 2017-04-06 02:28:06 +0800 CST2017-04-06 02:28:06 +0800 CST 2017-04-06 02:28:06 +0800 CST

Como reduzir valores de identidade para evitar estouro de inteiro?

  • 772

Eu tenho algumas tabelas de folhas (sem FK para elas) com algumas centenas de milhares de registros que são usados ​​para sincronizar alguns dados externos usando o Entity Framework ORM. Isso envolve alguns DELETEs seguidos por BULK INSERTs.

Para a maioria das tabelas, alguns valores antigos podem ficar para sempre, então não posso usar SEQUENCEs com CYCLE, como sugerido em um dos comentários.

Um efeito é que os valores de identidade continuarão aumentando ao longo do tempo e eu quero ser capaz de reduzir seus valores.

Esta pergunta e suas respostas explicam que os valores de identidade não podem ser atualizados, mesmo que identity_insertestejam ativados para a tabela.

Uma maneira rápida de fazer isso é transferir todos os dados para uma tabela de buffer e realizar a troca via renomear. Algo como o seguinte:

-- ActiveDirectoryCache_bak is the table I want to reduce identity values for
-- ActiveDirectoryCache_bak_buffer is a buffer table that will be renamed to ActiveDirectoryCache_bak once data transfer is ready

begin tran
select min(UserId), count(1) from ActiveDirectoryCache_bak
DBCC CHECKIDENT ('ActiveDirectoryCache_bak', NORESEED);  

-- Min UserId = 100, Count = 176041
-- Checking identity information: current identity value '204558', current column value '204558'.    

select * into ActiveDirectoryCache_bak_buffer
from ActiveDirectoryCache_bak
where 1 = 0

DBCC CHECKIDENT('ActiveDirectoryCache_bak_buffer', RESEED, 1)    

insert into ActiveDirectoryCache_bak_buffer
select LoginUsername, GivenName, MiddleName, Surname, EmailAddress
from ActiveDirectoryCache_bak

drop table ActiveDirectoryCache_bak

alter table ActiveDirectoryCache_bak_buffer add constraint PK_ActiveDirectoryCache_bak PRIMARY KEY (UserId)
EXEC sys.sp_rename 'ActiveDirectoryCache_bak_buffer', 'ActiveDirectoryCache_bak';

select min(UserId), count(1) from ActiveDirectoryCache_bak
DBCC CHECKIDENT ('ActiveDirectoryCache_bak', NORESEED);

-- Min UserId = 1, Count = 176041
-- Checking identity information: current identity value '176041', current column value '176041'.  

-- this should be replaced with commit when not in test mode
rollback

Eu posso fazer esse tipo de operação durante a noite e eles parecem levar apenas alguns segundos para o meu volume de dados (4 segundos para este exemplo).

Pergunta: Existem métodos para evitar a execução de uma cópia completa de dados para obter valores menores para colunas de identidade? Ou esta é uma das melhores abordagens no meu contexto (volume de dados razoável e poder bloquear algumas tabelas por vários segundos).

sql-server sql-server-2014
  • 3 3 respostas
  • 1560 Views

3 respostas

  • Voted
  1. Best Answer
    Solomon Rutzky
    2017-04-06T18:50:25+08:002017-04-06T18:50:25+08:00

    Você pode tentar simplesmente descartar e adicionar novamente a coluna Identity sem copiar a tabela inteira. Isso tem o mesmo efeito que você está tentando com o código na pergunta. Nenhuma das abordagens realmente lida com a manutenção de linhas existentes de acordo com a declaração "alguns valores antigos podem permanecer para sempre" da pergunta, mas para quaisquer situações que funcionem com o código na pergunta, o seguinte também deve funcionar.

    Você também deve considerar iniciar o intervalo de identidade no valor mínimo. Começar em 1 fornece pouco mais de 2,1 bilhões de valores, portanto, começar no valor mínimo (ou próximo a ele) fornece 4,2 bilhões de valores. Portanto, é menos provável que você precise de uma operação de reseed no futuro.

    CONFIGURAR

    -- DROP TABLE dbo.IdentityTest;
    CREATE TABLE dbo.IdentityTest
    (
      ID INT IDENTITY(10203, 7) NOT NULL CONSTRAINT [PK_IdentityTest] PRIMARY KEY,
      SomethingElse UNIQUEIDENTIFIER NOT NULL,
      SomeName NVARCHAR(256) NOT NULL
    );
    
    INSERT INTO dbo.IdentityTest ([SomethingElse], [SomeName])
      SELECT NEWID(), so1.[name] + N'~' + so2.[name]
      FROM   master.sys.all_columns so1
      CROSS JOIN master.sys.objects so2;
    -- 782,880 rows
    
    SELECT * FROM dbo.IdentityTest;
    

    Solte e recrie o Identity PK

    BEGIN TRY
      BEGIN TRAN;
    
      ALTER TABLE dbo.IdentityTest
        DROP CONSTRAINT [PK_IdentityTest];
    
      ALTER TABLE dbo.IdentityTest
        DROP COLUMN [ID];
    
      ALTER TABLE dbo.IdentityTest
        ADD [ID] INT
        IDENTITY(-2140000000, 1)
        NOT NULL
        CONSTRAINT [PK_IdentityTest]
          PRIMARY KEY;
    
      COMMIT TRAN;
    END TRY
    BEGIN CATCH
      IF (@@TRANCOUNT > 0)
      BEGIN
        ROLLBACK TRAN;
      END;
    
      THROW;
    END CATCH;
    
    SELECT * FROM dbo.IdentityTest;
    
    • 2
  2. RDFozz
    2017-04-06T07:20:14+08:002017-04-06T07:20:14+08:00

    Embora (como visto nos comentários), existam outras opções em potencial, parece que esta:

    • funciona;
    • não requer uma interrupção significativa;
    • não requer alterações em seu aplicativo;
    • poderia até ser automatizado, se necessário.

    Acho que é provavelmente a sua melhor opção. É o que eu usaria.

    • 1
  3. Michael Green
    2017-04-06T10:47:56+08:002017-04-06T10:47:56+08:00

    Você pergunta "Existem métodos para evitar a execução de uma cópia completa de dados para obter valores menores para colunas de identidade?" Para descobrir se há lacunas na sequência, será necessário ler cada linha (ou índice nessa coluna). Para preencher uma lacuna, será necessária uma atualização em cada linha após a lacuna. (Como você não pode atualizar uma IDENTIDADE, isso se torna uma exclusão seguida de uma inserção, com algumas jiggery-pokery de reseed no meio. Parece que pode ser mais lento do que uma abordagem de "cópia de tabela em massa", embora a justificativa para isso me iluda e provavelmente depende de algoritmos de leitura antecipada e de acesso ao disco.) Supondo que sejam os dados mais antigos que estão sendo excluídos, eles terão valores de identidade mais baixos, de modo que a maior parte da tabela será atualizada a cada vez. Uma cópia completa com leituras e gravações sequenciais parece ser mais eficiente.

    Uma abordagem é tornar a tabela particionada. Resemeie a identidade em uma tabela de trabalho. Alterne os dados antigos e alterne na mesa de trabalho. O tempo de inatividade será medido em (milis) segundos.

    Isenção de responsabilidade: eu não testei, então não tenho certeza de como ele reagirá. Será necessário considerar as gravações que ocorrem enquanto a mesa de trabalho está sendo preparada. Talvez duas partições ativas que passam por manutenção em horários alternativos?

    • 0

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