web-dev-qa-db-ja.com

非常に大きなテーブルのバックアップ

大きなテーブルの特定の値を更新する必要があります(推定の例では、「リソース」と呼ばれ、500万行を超えています)。したがって、変更を実行する前にバックアップを作成する必要があります。完全にバックアップされたテーブルを保存するのに十分なDB空き領域がありません。

どちらが最善の方法ですか?ブロックでこれを行う方法はありますか?たとえば、元のテーブルから最初の100K行をバックアップし、元のテーブルの100K行を更新し、バックアップしたテーブルからそれらの100K行を削除し、元のテーブルから次の100K行をバックアップし、同様に続行します。 。これは実現可能ですか?

7
iL_Marto

2つの考えが思い浮かびます。

  • この更新がテーブルに適切に影響しないことが心配な場合は、トランザクション内に更新を配置することを検討しましたか?.
  • 更新を行ってデータをクエリし、問題がなければ、トランザクションをコミットします。失敗した場合は、ロールバックを実行できます。

代替

BCPユーティリティ を参照して、SQL Serverの外部のフラットファイルにテーブルを抽出することもできます。

おそらく、テーブルの内容を、それほどストレージの圧力がかかっていない場所に格納することができます。更新プロセスが失敗した場合、コンテンツをテーブルに復元しようとする可能性があります。

4
Rob

既存のテーブルのみのバックアップをnew_tableに取り、テーブルを更新できます。問題が発生した場合は、常にバックアップテーブルを元に戻すことができます。

例:

-- SCRIPT TO BACKUP A TABLE
SELECT * INTO <NEW_TABLE> FROM CURRENT_TABLE

単一のテーブルのバックアップを取ることは、完全なデータベースのバックアップを取ることよりもはるかに少ないです。

すべてがうまくいけば、<NEW_TABLE>

0
JaMeEL

単一のテーブルをバックアップしないでください。通常はお勧めできません。常にデータベース全体をバックアップしてください

まず第一に。データベースが稼働していないことを想定しています。そうしないと、バックアップを復元すると操作が失われる可能性があります。

あなたがしていることを知っていると仮定して、あなたが望む答え:

テーブルのバックアップを作成する簡単な方法は、その内容を含む別のテーブルを作成することです。

CREATE Table tableBackup as select * from tableToBackup;

問題が発生した場合は、元のテーブルからタプルを削除し、バックアップデータベースからタプルを挿入します。

もちろん、1つのテーブルをバックアップすることは通常悪い考えであることを十分に認識しておく必要があります。通常、データベースの整合性はデータベース全体の値に依存します(たとえば、別のテーブルの値は、このテーブルのタプルの存在に依存する可能性があります-たとえば、外部キー関係)。

バックアップするテーブルと他のテーブルの間に参照制約がある場合、上記で提案した方法を使用して元のテーブルを復元できない可能性があります。

したがって、何をしているのかわからない場合は、単一のテーブルではなくデータベース全体をバックアップしてください。これがどのように行われるかについては、選択したデータベースのドキュメントを確認してください。

0
dmg

@dmgの発言に追加します。単一のテーブルのバックアップには問題が生じる可能性があります。たとえば、「大きな」テーブルがデータベースの90%である場合、RIは別として、テーブルをバックアップするだけではあまり役に立ちません。 SQL 2008を使用している場合は、compressing your backupsであることを確認してください。かなりの圧縮率が得られ、実際には完全バックアップを実行できる場合があります。

別のオプションは、transaction logバックアップを取ることです。これは、変更を加える前に大規模なデータベースを扱うときに通常行うことです。それらは常にフルバックアップよりもずっと小さくなければなりません(特に頻繁にバックアップを取る場合)。圧縮するとさらに小さくなります。

これで、データベースがsimple recoveryに設定されている場合は機能しません。その場合、他の唯一の従来のバックアップオプションはdifferential backupsを調べることです。これらは実際にはかなり大きくなる可能性があります。ただし、最後の完全バックアップが最近行われた場合、またはデータベースのごく一部のみを変更した場合は、これが実行可能なオプションになる場合があります。一方、データベースがsimpleに設定されている場合は、変更前に回復可能であることを心配する必要はありません。

最後になりましたが(SQL 2005以降)OUTPUT句があります。この便利な小さな句により、コマンドの実行中に加えた変更を出力できます。それらは、テーブル変数またはテーブルに格納できます。基本的に、これらは通常トリガーでのみ表示されるINSERTEDおよびDELETEDテーブルへのアクセスを提供します。変更(前後両方)を別のテーブルにバックアップできます。この方法では、変更された行と列のみをバックアップします。もちろん、主キーも含めてください。これが BOLエントリ です。そして、これがBOLの例です。この特定の例では、10行のデータのうち4列のみが保存されます。テーブルがたまたま5または10 mil行だったとしても。

USE AdventureWorks;
GO
DECLARE @MyTableVar table(
    EmpID int NOT NULL,
    OldVacationHours int,
    NewVacationHours int,
    ModifiedDate datetime);
UPDATE TOP (10) HumanResources.Employee
SET VacationHours = VacationHours * 1.25 
OUTPUT INSERTED.EmployeeID,
       DELETED.VacationHours,
       INSERTED.VacationHours,
       INSERTED.ModifiedDate
INTO @MyTableVar;
0
Kenneth Fisher

投稿されたテーブル作成構文は機能しません、afaik。

単一のテーブルをバックアップする簡単な方法は次のとおりです。

SELECT * INTO [backup-table] FROM [source-table]

その後、不要なときに[backup-table]を削除できます。

これは、diff db(diffスピンドルセットにある可能性があります)などに渡って行うことができます。

これまでのところ、与えられた回答では、ベーステーブルデータはバックアップしていますが、テーブル自体はバックアップしていません。テーブルには他にも多くの属性があり、SELECT * INTO基本的に、セルの値と列の構造を取得します。完全ではありませんが、考慮すべきいくつかの追加属性:

  • パーティショニングスキーム/機能
  • インデックス
  • 外部キーの関係
  • オブジェクトレベルの権限
  • -拡張プロパティ
  • 等.

これは非常に大きなテーブルなので、パーティション化や重いインデックス付けを見つけても驚くことはありません。これまでのIMOの最良の答えは、データベース全体をバックアップすることです。それが適切でない場合は、スキーマ全体とサポートスキーマをスクリプト化します(パーティション分割のようにテーブルの外にあるアイテムの場合)。そのコピーを用意してから、SELECT INTO.

もちろん、Kim Trippのような非常に知識のある人は、データをダンプした後にインデックスを追加し、場合によってはパーティション分割を推奨します。これはおそらく健全なアドバイスです。データをダンプした後にパーティションを作成する場合は、チェック制約を使用してパーティションの削除が確実に行われるようにしてください。ただし、実際に構成されている場合は、この点を検討する必要があります。

0
Ali Razeghi