sql >> Databáze >  >> RDS >> Sqlserver

Nejrychlejší způsob aktualizace 120 milionů záznamů

Jediný rozumný způsob aktualizace tabulky 120 milionů záznamů je pomocí SELECT příkaz, který vyplní sekundu stůl. Když to děláte, musíte být opatrní. Pokyny níže.

Jednoduchý případ

Pro tabulku bez seskupeného indexu během doby bez souběžného DML:

  • SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
  • znovu vytvořit indexy, omezení atd. v nové tabulce
  • přepnout staré a nové pomocí ALTER SCHEMA ... PŘENOS.
  • zahodit starý stůl

Pokud nemůžete vytvořit schéma klonu, postačí jiný název tabulky ve stejném schématu. Nezapomeňte po přepnutí přejmenovat všechna svá omezení a spouštěče (pokud jsou k dispozici).

Nejednoduchý případ

Nejprve znovu vytvořte BaseTable se stejným názvem pod jiným schématem, např. clone.BaseTable . Použití samostatného schématu později zjednoduší proces přejmenování.

  • Zahrňte seskupený index , je-li to relevantní. Pamatujte, že primární klíče a jedinečná omezení mohou být seskupená, ale ne nutně.
  • Zahrňte sloupce identity a vypočítané sloupce , je-li to relevantní.
  • Zahrňte svůj nový sloupec INT , kamkoli patří.
  • Nezahrnujte kteroukoli z následujících možností:
    • spouštěče
    • cizí klíčová omezení
    • neshlukované indexy/primární klíče/jedinečná omezení
    • zkontrolujte omezení nebo výchozí omezení. Ve výchozích nastaveních se příliš neliší, ale snažíme se, aby byly věci minimální.

Poté otestujte svou přílohu s 1000 řádky:

-- assuming an IDENTITY column in BaseTable
SET IDENTITY_INSERT clone.BaseTable ON
GO
INSERT clone.BaseTable WITH (TABLOCK) (Col1, Col2, Col3)
SELECT TOP 1000 Col1, Col2, Col3 = -1
FROM dbo.BaseTable
GO
SET IDENTITY_INSERT clone.BaseTable OFF

Prozkoumejte výsledky. Pokud je vše v pořádku:

  • zkrátit tabulku klonů
  • ujistěte se, že databáze je v hromadném nebo jednoduchém modelu obnovení
  • proveďte úplné vložení.

Bude to chvíli trvat, ale ne tak dlouho jako aktualizace. Po dokončení zkontrolujte data v klonovací tabulce, abyste se ujistili, že je vše v pořádku.

Poté znovu vytvořte všechny neklastrované primární klíče/jedinečná omezení/indexy a omezení cizích klíčů (v tomto pořadí). Znovu vytvořte výchozí a případně zkontrolujte omezení. Znovu vytvořte všechny spouštěče. Znovu vytvořte každé omezení, index nebo spouštěč v samostatné dávce. např.:

ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here

Nakonec přesuňte dbo.BaseTable na záložní schéma a clone.BaseTable do schématu dbo (nebo kdekoli, kde má váš stůl žít).

-- -- perform first true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
-- GO
-- -- create a backup schema, if necessary
-- CREATE SCHEMA backup_20100914
-- GO
BEGIN TRY
  BEGIN TRANSACTION
  ALTER SCHEMA backup_20100914 TRANSFER dbo.BaseTable
  -- -- perform second true-up operation here, if necessary
  -- EXEC clone.BaseTable_TrueUp
  ALTER SCHEMA dbo TRANSFER clone.BaseTable
  COMMIT TRANSACTION
END TRY
BEGIN CATCH
  SELECT ERROR_MESSAGE() -- add more info here if necessary
  ROLLBACK TRANSACTION
END CATCH
GO

Pokud potřebujete uvolnit místo na disku, můžete svou původní tabulku v tuto chvíli zahodit, i když může být rozumné ponechat si ji ještě chvíli.

Netřeba dodávat, že v ideálním případě se jedná o offline úkon. Pokud máte lidi, kteří během provádění této operace upravují data, budete muset provést operaci ověření pomocí přepínače schématu. Doporučuji vytvořit spouštěč na dbo.BaseTable pro přihlášení všech DML do samostatné tabulky. Povolte tuto spoušť před spuštěním vkládání. Poté ve stejné transakci, jakou provádíte přenos schématu, použijte tabulku protokolu k provedení oprav. Nejprve to otestujte na podmnožině dat! Delty lze snadno pokazit.



  1. Jak funguje funkce FROM_BASE64() v MySQL

  2. Jaký je nejrychlejší způsob hromadného vkládání velkého množství dat na SQL Server (klient C#)

  3. Používají různé databáze různé uvozovky?

  4. Jak odstraním rozšířené znaky ASCII z řetězce v T-SQL?