Design, migrate, and run scalable, highly available databases on Google Cloud across relational and NoSQL services, and track your readiness for the Professional Cloud Database Engineer exam.
Prepare and test your skills
Prepare and test your skills
Engine-specific import and export is the practice of matching each Google Cloud database to its supported utility and file format so data moves without losing types or structure. Cloud Spanner (opens in a new tab) uses Dataflow jobs that read from and write to Cloud Storage (opens in a new tab) with Avro or CSV (opens in a new tab) files plus JSON manifests. Firestore (opens in a new tab) in Datastore mode uses managed export and import operations that also stage files in Cloud Storage. Choosing the wrong format or omitting the manifest breaks fidelity on import.
A Cloud Spanner Avro export is a Dataflow job that copies table data from the Spanner database to a folder in a Cloud Storage bucket. Data flows from Spanner tables through Dataflow workers to Avro files in the destination folder, so the job depends on both Spanner compute capacity and Dataflow access to the bucket. The export folder created by the job holds everything needed for a later import or inspection.
The export folder contains:
spanner-export.json that describes the overall exportTableName-manifest.json for each table that lists its data filesTableName.avro-#####-of-##### data files where the first number is the file index starting at zero and the second is the total file count, such as Songs.avro-00001-of-00002ChangeStreamName-manifest.json and ChangeStreamName.avro-00000-of-00001 for each change stream, where the Avro file holds only the schema with empty dataTo import a Spanner Avro export, data flows in reverse from the Cloud Storage folder through a Dataflow import job into a new Spanner database. The operator selects the export folder itself in the console, enters a new database name that does not already exist in the instance, and chooses the dialect for the new database as GoogleSQL or PostgreSQL. The import job creates the database during the run, and the new database can optionally be protected with a customer-managed encryption key.
A Cloud Spanner CSV export and import uses CSV data files plus a JSON manifest file stored together in a Cloud Storage bucket. Data flows from Spanner through Dataflow to CSV files on export, and from CSV files through Dataflow to Spanner on import. Because CSV does not carry full Spanner type information on its own, the JSON manifest specifies which destination tables are populated by which CSV files, and the target tables must already exist with the correct schema.
Importing CSV files into Spanner follows an ordered workflow:
This order matters because the Dataflow job depends on both the manifest and the pre-created schema. If the manifest is missing or the table definition does not match the file columns, the import cannot correctly assign data to tables and types.
Importing Avro files from a non-Spanner database into Cloud Spanner preserves more type fidelity than CSV because Avro carries column types. Data flows from Avro files in Cloud Storage through a Dataflow job into pre-created Spanner tables, so the workflow depends on creating the Spanner schema before running the import. The operator must also create a spanner-export.json file in the bucket that points to the destination tables and their Avro files, then run the Dataflow import with the gcloud CLI.
Avro source columns must use supported types, and each type maps to a specific Spanner column type. A column of type BYTES with logicalType=decimal, precision=38, and scale=9 imports as Spanner NUMERIC; without those exact specifications the same field imports as Spanner BYTES. A LONG or STRING that stores a timestamp value can import as Spanner TIMESTAMP when the target column is defined that way. The table below shows the supported mappings.
| Avro column type | Spanner column type |
|---|---|
ARRAY | ARRAY |
BOOL | BOOL |
BYTES | BYTES, or NUMERIC when logicalType=decimal, precision=38, and scale=9 |
DOUBLE | FLOAT64 equivalent DOUBLE |
FLOAT | FLOAT |
INT | INT64 mapping for integer values |
LONG | INT64, or TIMESTAMP when storing timestamp values |
STRING | STRING, or TIMESTAMP when storing timestamp values |
No special metadata or file naming convention is required for non-Spanner Avro source files. Any Avro primitive type and the array complex type can be used on export, as long as each column fits one of the supported Avro types in the table.
Firestore managed export and import operations authorize as the Firestore service agent and stage data in a Cloud Storage bucket. The service agent is service-PROJECT_NUMBER@gcp-sa-firestore.iam.gserviceaccount.com, which replaces the legacy App Engine service account PROJECT_ID@appspot.gserviceaccount.com shared by multiple services. If the Cloud Storage bucket is in the same project as the Firestore database, the service agent can access the bucket by default; if the bucket is in another project, the operator must grant the service agent access to that bucket.
An export of all entities without an entity filter cannot be used for selective restore or for BigQuery loading. Data exported without one or more kind names in the entity filter cannot be loaded into BigQuery, and a subset of kinds and namespaces cannot be imported from an export of all entities. To keep BigQuery compatibility, the export request must include an entity filter with kind names, and each kind generates a BigQuery table schema where each unique property becomes a column.
BigQuery enforces a limit of 10,000 columns per table, which affects wide Firestore kinds. If a kind schema exceeds 10,000 columns, the export tries to stay under the limit by treating embedded entities as blobs, which allows loading but prevents querying properties inside those embedded entities. If the column count still exceeds 10,000, no BigQuery schema is generated for that kind and its data cannot be loaded into BigQuery.
Exam tip: An export of all kinds and namespaces cannot be loaded into BigQuery; include one or more kind names in the entity filter when BigQuery loading is required.
Dataflow import and export jobs for Cloud Spanner require specific Identity and Access Management roles on the Dataflow worker service account. The worker identity must be able to read Spanner, run Dataflow, and read and write Cloud Storage objects, with an extra admin role for imports that create databases. Without these grants, data cannot flow between Spanner and the Cloud Storage staging bucket.
The required roles on the Dataflow worker service account are:
roles/spanner.viewer)roles/dataflow.worker)roles/storage.admin)roles/spanner.databaseReader)roles/spanner.databaseAdmin), which is required only for import jobsCompute Engine quotas bound how many resources Dataflow can use, and these quotas represent the maximum allowed rather than guaranteed usage. Recommended starting values are 200 CPUs, 200 in-use IP addresses, and 50 TB of standard persistent disk. Dataflow provides autoscaling so the job pays only for resources actually used, and the Dataflow UI shows a warning icon if the job could use more resources, though the job should still finish.
Optimizing performance and validating data integrity means moving large volumes quickly without losing accuracy. BigQuery (opens in a new tab) uses Cloud Storage (opens in a new tab) as the staging area for load and export operations, efficient file formats and incremental transfers to reduce movement size, and partitioning and clustering to keep queries fast after the load. After import, schema alignment and data completeness are verified by comparing types, structures, counts, and query results between source and target.
Cloud Storage is the staging layer that data flows through when moving data into or out of BigQuery. Data flows from the source system to a Cloud Storage bucket and then from the bucket into BigQuery, and exports flow in the reverse direction from BigQuery to the bucket. For a Snowflake (opens in a new tab) to BigQuery movement, the export is prepared with a named file format set to PARQUET, a storage integration that permits the bucket locations, and an external stage that references the integration and file format. This staged approach lets large datasets land in durable object storage first, so the load into BigQuery can read from files rather than from a live source connection.
The BigQuery Data Transfer Service with the Snowflake connector reduces movement size by supporting incremental transfer. An incremental transfer moves only data that changed since the last transfer instead of loading the entire dataset each time, which lowers transfer time and cost for large tables. The connector can also automatically detect table schema and data types during transfer, so schema discovery does not require a separate manual step.
Physical design preserves performance after the data arrives. Both BigQuery and Snowflake use a massively parallel processing (MPP) architecture where queries are distributed across multiple servers, and BigQuery adds slots as the unit of computational capacity for query execution. BigQuery supports explicit partitioning and clustering to control how data is distributed and organized, which can improve runtime performance and cost. The SQL translation service automatically handles table clustering translation when migrating data definition language (DDL) and can be configured to customize partitioning and clustering.
Schema alignment verification confirms that tables, data types, and security controls mean the same thing in the target as in the source. Translated queries must be reviewed to verify that data types and table structures were correctly handled, and views and user-defined functions (UDFs) must be verified so their controls become authorized views and authorized UDFs in BigQuery. Row-level and column-level controls are rebuilt with BigQuery policy tags, authorized views, and related access controls mapped from the source roles through Identity and Access Management (IAM).
Firestore (opens in a new tab) and Datastore mode exports have strict schema rules for BigQuery loads:
Exam tip: An export without an entity filter cannot be loaded into BigQuery; include one or more kind names in the export when BigQuery is the destination.
Data completeness validation confirms that the imported data is whole and returns the same answers as the source. A repeatable validation sequence moves from test design to comparison to correction:
This post-transfer work is part of normal migration planning. The timeline accounts for validating, auditing, and testing tasks after data transfer takes place, and duration depends on database size, business logic complexity, application usage, and team availability. The technical design document records business requirements, recovery time objective (RTO), recovery point objective (RPO), migration details, effort estimates, and migration validation recommendations, so validation is planned before the first load runs.
Secure access for data transfer means that both the person who starts an export or import and the service account that moves the bytes have only the permissions they need. In Google Cloud, Identity and Access Management (IAM) controls who can act, while Cloud Storage bucket permissions control where the service account can read and write. A secure pipeline therefore connects three parts in order: the user identity to the database service, the database service identity to the bucket, and the bucket policy back to both identities.
Every database transfer uses two separate identities with different jobs. The user account is the Google Account that signs in to create connection profiles, upload files, and start export, import, or migration jobs. The service account is the Google-managed identity that actually reads and writes data, such as the Firestore (opens in a new tab) service agent service-PROJECT_NUMBER@gcp-sa-firestore.iam.gserviceaccount.com, the Database Migration Service (DMS) (opens in a new tab) service account service-PROJECT_NUMBER@gcp-sa-datamigration.iam.gserviceaccount.com, or the Google SecOps export service account. You can see which identity will run Firestore jobs on the Databases page by selecting a database, clicking Import/Export, and viewing the authorization account next to the Import/Export jobs run as label.
IAM roles for users define who can create, cancel, and view data export jobs without granting broad Viewer, Editor, or Owner access to the whole project. For SecOps data exports (opens in a new tab) , the user needs data export permissions that are grouped into predefined roles for full or read-only management:
chronicle.dataExports.fetchServiceAccountForDataExport to discover the export service accountchronicle.dataExports.create to create export jobschronicle.dataExports.cancel to cancel export jobschronicle.dataExports.get to view a single jobchronicle.dataExports.list to view job historyThe Chronicle API Admin role grants full permission to create, update, cancel, and view export jobs with global access, while the Chronicle API Viewer role grants read-only access to job configurations and history. For DMS Oracle migrations, the user needs the Database Migration Admin role (roles/datamigration.admin) plus a destination role such as AlloyDB Admin (roles/alloydb.admin) or Cloud SQL Editor (roles/cloudsql.editor). When predefined roles grant too much access, create a custom IAM role with only the needed permissions and add the Chronicle API Restricted Data Access role with an IAM condition such as resource.name.endsWith("/dataAccessScopes/scope_test") to limit the user to specific data access scopes.
Cloud Storage bucket permissions determine whether the service account can deliver exported files or read files for import. The destination bucket should be private to prevent unauthorized access and, for SecOps exports, created in the same region as the tenant. The SecOps service account then needs bucket-level roles so data flows from the SecOps service to the bucket, specifically Storage Object Admin (roles/storage.objectAdmin) to write objects and Legacy Bucket Reader (roles/storage.legacyBucketReader) to read bucket metadata.
Firestore follows a project-boundary rule that separates default access from explicit grants. Import and export workflows that stay within the same project do not require permission changes because the Firestore service agent can access buckets in the same project by default. Operations that use a bucket in another project fail unless you grant that bucket access to the source project's Firestore service agent. The Firestore Service Agent role grants both read and write permission on the bucket, so use a custom role when you need to grant only read for imports or only write for exports.
Exam tip: The Firestore Service Agent role grants both read and write on a Cloud Storage bucket; same-project buckets work by default, but cross-project buckets need an explicit grant or the job fails.
Migration to the Firestore service agent moves Firestore import and export jobs from the older App Engine service account to the dedicated Firestore service agent. The recommended project-level migration localizes the effect to one Firestore project, while an organization-wide policy constraint enforces compliance across all projects but does not fix existing bucket permissions:
| Approach | Scope of effect | Effect on existing buckets |
|---|---|---|
| Migrate by checking bucket permissions | Single Firestore project | Identifies recently used buckets missing access and lets you fix them before migrating |
| Add organization policy constraint | Entire organization | Enforces service-agent use for compliance but does not migrate existing bucket permissions |
The project-level migration job (opens in a new tab) follows an ordered check, fix, and confirm workflow:
Migration cannot be undone, so complete all needed bucket fixes before the final confirmation and verify the new authorization account on the Import/Export page after the alert reports completion.
spanner-export.json, per-table manifests, and TableName.avro-#####-of-##### data files.Last updated