이전 데이터 액세스

BigQuery를 사용하면 시간 이동 기간 내에 변경되었거나 삭제된 BigQuery에 저장된 데이터를 쿼리하고 복원할 수 있습니다.

특정 시점의 데이터 쿼리

FOR SYSTEM_TIME AS OF 절을 사용하여 시간 이동 기간 이내의 어느 시점에서든 테이블의 이전 데이터를 쿼리할 수 있습니다. 이 절은 상수 타임스탬프 표현식을 사용해서 해당 타임스탬프에서 현재였던 테이블 버전을 참조합니다. 테이블은 BigQuery에 저장되어야 하며, 외부 테이블일 수 없습니다. SYSTEM_TIME AS OF를 사용할 때는 테이블 크기에 제한이 없습니다.

예를 들어 다음 쿼리는 1시간 전의 이전 테이블 버전을 반환합니다.

SELECT *
FROM `mydataset.mytable`
  FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR);

타임스탬프가 시간 이동 기간 이전 또는 테이블 생성 이전의 시간을 지정하는 경우 쿼리가 실패하고 다음과 비슷한 오류가 반환됩니다.

Invalid snapshot time 1601168925462 for table
myproject:mydataset.table1@1601168925462. Cannot read before 1601573410026.

CREATE OR REPLACE TABLE 문을 사용하여 기존 테이블을 대체한 후 FOR SYSTEM_TIME AS OF를 사용하여 테이블의 이전 버전을 쿼리할 수 있습니다.

테이블이 삭제된 경우 쿼리가 실패하고 다음과 비슷한 오류가 반환됩니다.

Not found: Table myproject:mydataset.table was not found in location LOCATION

특정 시점의 테이블 복원

이전 데이터를 새 테이블에 복사하여 이전 데이터에서 테이블을 복원할 수 있습니다. 시간 이동 기간 이내에만 테이블을 복원하면, 테이블이 삭제되었거나 만료되었더라도 이전 데이터 복사가 작동합니다.

이전 데이터에서 테이블을 복원하면 소스 테이블의 태그가 대상 테이블에 복사되지 않습니다. 테이블 파티션 나누기 정보도 대상 테이블에 복사되지 않습니다. 원래 테이블의 파티셔닝 스키마를 다시 만들려면 Cloud Logging에서 초기 테이블 생성 요청을 확인하고 이 정보를 사용하여 복원된 테이블을 파티셔닝하면 됩니다.

@<time> 시간 데코레이터를 사용하여 테이블을 새 테이블에 복사하여 삭제되었지만 아직 시간 이동 기간 내의 테이블을 복원할 수 있습니다. 시간 데코레이터를 사용하더라도 삭제된 테이블을 쿼리할 수는 없습니다. 먼저 복원해야 합니다.

@<time> 시간 데코레이터와 함께 다음 구문을 사용합니다.

  • tableid@TIME: 여기서 TIME은 Unix epoch 이후의 밀리초 수입니다.
  • tableid@-TIME_OFFSET: 여기서 TIME_OFFSET은 현재 시간 기준의 상대 오프셋(밀리초)입니다.
  • tableid@0: 사용 가능한 가장 오래된 이전 데이터를 지정합니다.

테이블을 복원하려면 다음 옵션 중 하나를 선택합니다.

콘솔

Google Cloud 콘솔을 사용하여 테이블을 삭제 취소할 수 없습니다.

bq

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 테이블을 복원하려면 먼저 테이블이 있었던 시점의 UNIX 타임스탬프 (밀리초 단위)를 확인합니다. Linux date 명령어를 사용하여 일반 타임스탬프 값에서 Unix 타임스탬프를 생성할 수 있습니다.

    date -d '2023-08-04 16:00:34.456789Z' +%s000
    
  3. 그런 다음 @<time> 시간 이동 데코레이터와 함께 bq copy 명령어를 사용하여 테이블 복사 작업을 수행합니다.

    예를 들어 1418864998000 시점의 mydataset.mytable 테이블을 새 테이블인 mydataset.newtable로 복사하려면 다음 명령어를 입력합니다.

    bq cp mydataset.mytable@1418864998000 mydataset.newtable
    

    (선택사항) --location 플래그를 지정하고 값을 사용자 위치로 설정합니다.

    상대 오프셋을 지정할 수도 있습니다. 다음 예시에서는 1시간 전의 테이블 버전을 복사합니다.

    bq cp mydataset.mytable@-3600000 mydataset.newtable
    
  4. Go

    이 샘플을 사용해 보기 전에 BigQuery 빠른 시작: 클라이언트 라이브러리 사용Go 설정 안내를 따르세요. 자세한 내용은 BigQuery Go API 참고 문서를 확인하세요.

    BigQuery에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 클라이언트 라이브러리의 인증 설정을 참조하세요.

    import (
    	"context"
    	"fmt"
    	"time"
    
    	"cloud.google.com/go/bigquery"
    )
    
    // deleteAndUndeleteTable demonstrates how to recover a deleted table by copying it from a point in time
    // that predates the deletion event.
    func deleteAndUndeleteTable(projectID, datasetID, tableID string) error {
    	// projectID := "my-project-id"
    	// datasetID := "mydataset"
    	// tableID := "mytable"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()
    
    	ds := client.Dataset(datasetID)
    	if _, err := ds.Table(tableID).Metadata(ctx); err != nil {
    		return err
    	}
    	// Record the current time.  We'll use this as the snapshot time
    	// for recovering the table.
    	snapTime := time.Now()
    
    	// "Accidentally" delete the table.
    	if err := client.Dataset(datasetID).Table(tableID).Delete(ctx); err != nil {
    		return err
    	}
    
    	// Construct the restore-from tableID using a snapshot decorator.
    	snapshotTableID := fmt.Sprintf("%s@%d", tableID, snapTime.UnixNano()/1e6)
    	// Choose a new table ID for the recovered table data.
    	recoverTableID := fmt.Sprintf("%s_recovered", tableID)
    
    	// Construct and run a copy job.
    	copier := ds.Table(recoverTableID).CopierFrom(ds.Table(snapshotTableID))
    	copier.WriteDisposition = bigquery.WriteTruncate
    	job, err := copier.Run(ctx)
    	if err != nil {
    		return err
    	}
    	status, err := job.Wait(ctx)
    	if err != nil {
    		return err
    	}
    	if err := status.Err(); err != nil {
    		return err
    	}
    
    	ds.Table(recoverTableID).Delete(ctx)
    	return nil
    }
    

    자바

    이 샘플을 사용해 보기 전에 BigQuery 빠른 시작: 클라이언트 라이브러리 사용Java 설정 안내를 따르세요. 자세한 내용은 BigQuery Java API 참고 문서를 확인하세요.

    BigQuery에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 클라이언트 라이브러리의 인증 설정을 참조하세요.

    import com.google.cloud.bigquery.BigQuery;
    import com.google.cloud.bigquery.BigQueryException;
    import com.google.cloud.bigquery.BigQueryOptions;
    import com.google.cloud.bigquery.CopyJobConfiguration;
    import com.google.cloud.bigquery.Job;
    import com.google.cloud.bigquery.JobInfo;
    import com.google.cloud.bigquery.TableId;
    
    // Sample to undeleting a table
    public class UndeleteTable {
    
      public static void runUndeleteTable() {
        // TODO(developer): Replace these variables before running the sample.
        String datasetName = "MY_DATASET_NAME";
        String tableName = "MY_TABLE_TABLE";
        String recoverTableName = "MY_RECOVER_TABLE_TABLE";
        undeleteTable(datasetName, tableName, recoverTableName);
      }
    
      public static void undeleteTable(String datasetName, String tableName, String recoverTableName) {
        try {
          // Initialize client that will be used to send requests. This client only needs to be created
          // once, and can be reused for multiple requests.
          BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
    
          // "Accidentally" delete the table.
          bigquery.delete(TableId.of(datasetName, tableName));
    
          // Record the current time.  We'll use this as the snapshot time
          // for recovering the table.
          long snapTime = System.currentTimeMillis();
    
          // Construct the restore-from tableID using a snapshot decorator.
          String snapshotTableId = String.format("%s@%d", tableName, snapTime);
    
          // Construct and run a copy job.
          CopyJobConfiguration configuration =
              CopyJobConfiguration.newBuilder(
                      // Choose a new table ID for the recovered table data.
                      TableId.of(datasetName, recoverTableName),
                      TableId.of(datasetName, snapshotTableId))
                  .build();
    
          Job job = bigquery.create(JobInfo.of(configuration));
          job = job.waitFor();
          if (job.isDone() && job.getStatus().getError() == null) {
            System.out.println("Undelete table recovered successfully.");
          } else {
            System.out.println(
                "BigQuery was unable to copy the table due to an error: \n"
                    + job.getStatus().getError());
            return;
          }
        } catch (BigQueryException | InterruptedException e) {
          System.out.println("Table not found. \n" + e.toString());
        }
      }
    }

    Node.js

    이 샘플을 사용해 보기 전에 BigQuery 빠른 시작: 클라이언트 라이브러리 사용Node.js 설정 안내를 따르세요. 자세한 내용은 BigQuery Node.js API 참고 문서를 확인하세요.

    BigQuery에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 클라이언트 라이브러리의 인증 설정을 참조하세요.

    // Import the Google Cloud client library
    const {BigQuery} = require('@google-cloud/bigquery');
    const bigquery = new BigQuery();
    
    async function undeleteTable() {
      // Undeletes "my_table_to_undelete" from "my_dataset".
    
      /**
       * TODO(developer): Uncomment the following lines before running the sample.
       */
      // const datasetId = "my_dataset";
      // const tableId = "my_table_to_undelete";
      // const recoveredTableId = "my_recovered_table";
    
      /**
       * TODO(developer): Choose an appropriate snapshot point as epoch milliseconds.
       * For this example, we choose the current time as we're about to delete the
       * table immediately afterwards.
       */
      const snapshotEpoch = Date.now();
    
      // Delete the table
      await bigquery
        .dataset(datasetId)
        .table(tableId)
        .delete();
    
      console.log(`Table ${tableId} deleted.`);
    
      // Construct the restore-from table ID using a snapshot decorator.
      const snapshotTableId = `${tableId}@${snapshotEpoch}`;
    
      // Construct and run a copy job.
      await bigquery
        .dataset(datasetId)
        .table(snapshotTableId)
        .copy(bigquery.dataset(datasetId).table(recoveredTableId));
    
      console.log(
        `Copied data from deleted table ${tableId} to ${recoveredTableId}`
      );
    }

    Python

    이 샘플을 사용해 보기 전에 BigQuery 빠른 시작: 클라이언트 라이브러리 사용Python 설정 안내를 따르세요. 자세한 내용은 BigQuery Python API 참고 문서를 확인하세요.

    BigQuery에 인증하려면 애플리케이션 기본 사용자 인증 정보를 설정합니다. 자세한 내용은 클라이언트 라이브러리의 인증 설정을 참조하세요.

    import time
    
    from google.cloud import bigquery
    
    # Construct a BigQuery client object.
    client = bigquery.Client()
    
    # TODO(developer): Choose a table to recover.
    # table_id = "your-project.your_dataset.your_table"
    
    # TODO(developer): Choose a new table ID for the recovered table data.
    # recovered_table_id = "your-project.your_dataset.your_table_recovered"
    
    # TODO(developer): Choose an appropriate snapshot point as epoch
    # milliseconds. For this example, we choose the current time as we're about
    # to delete the table immediately afterwards.
    snapshot_epoch = int(time.time() * 1000)
    
    # ...
    
    # "Accidentally" delete the table.
    client.delete_table(table_id)  # Make an API request.
    
    # Construct the restore-from table ID using a snapshot decorator.
    snapshot_table_id = "{}@{}".format(table_id, snapshot_epoch)
    
    # Construct and run a copy job.
    job = client.copy_table(
        snapshot_table_id,
        recovered_table_id,
        # Must match the source and destination tables location.
        location="US",
    )  # Make an API request.
    
    job.result()  # Wait for the job to complete.
    
    print(
        "Copied data from deleted table {} to {}".format(table_id, recovered_table_id)
    )

시간 이동 기간에 허용되는 것보다 나중에 테이블을 복원해야 할 것으로 예상되는 경우, 테이블의 테이블 스냅샷을 만듭니다. 자세한 내용은 테이블 스냅샷 소개를 참조하세요.

논리 뷰는 직접 복원할 수 없습니다. 자세한 내용은 뷰 복원을 참고하세요.

다음 단계