View a markdown version of this page

Schema unnesting - AWS Glue

Schema unnesting

When integrating with analytics services through Zero-ETL, you can choose how nested structures are represented in the target tables. AWS Glue Zero-ETL provides schema unnesting options to flatten complex data structures into more analytics-friendly formats.

Unnesting options

When creating a Zero-ETL integration with a source, you can choose from the following unnesting options. These options correspond to specific enumeration values that you'll use when calling the CreateIntegrationTableProperty API. For all unnest options, we would traverse to most inner layer and map DDB type to target spark/iceberg primitive type with best efforts. The type mapping between source DDB and target table is as below:

DDB source data typeTarget table data type
"S"StringType
"B"BinaryType
"N"DoubleType
"BOOL"BooleanType
"SS"ArrayType(StringType)
"NS"ArrayType(DoubleType)
"BS"ArrayType(BinaryType)
"L"ArrayType(StringType)
"NULL"Ignore
"M"StructType (TOP/NOUNNEST)
No unnesting - NO_UNNEST

API value: NO_UNNEST

Preserves the original nested structure of Amazon DynamoDB items. Maps and lists are stored as structured columns in the target.

Best for: Preserving the exact structure of your Amazon DynamoDB data when your analytics tools can work with nested data.

Top level - TOP_LEVEL

API value: TOP_LEVEL

Flattens the top level of nested maps into individual columns. List structures remain nested.

Preserves the exact structure of your Amazon DynamoDB data when your analytics tools can work with nested data with all DDB type information removed.

Best for: Balancing between data structure preservation and query simplicity when your Amazon DynamoDB table items have a consistent schema.

Unnest all levels - FULL (default)

API value: FULL

Recursively flattens all nested structures (maps and lists) into individual columns with dot notation for naming.

Best for: Maximizing query simplicity when working with deeply nested structures and analytics tools that prefer flat schemas.

Note

Full unnesting can lead to very wide tables with many columns if your DynamoDB data has variable or deeply nested structures.

Example Using unnesting options in the API

When configuring schema unnesting through the CreateIntegrationTableProperty API, specify the unnesting option in the UnnestSpec parameter:

aws glue create-integration-table-property --resource-arn "arn:aws:glue:us-east-1:123456789012:database/my_db" --table-name "my-table" --cli-input-json '{ "TargetTableConfig": { "UnnestSpec": "FULL", "TargetTableName": "my-target-table", } }'

Unnesting examples

Consider a DynamoDB item with the following structure:

// Input DynamoDB Record { "Item": { "col_1": { "S": "value_1" }, "col_2": { "M": { "col_3": { "M": { "id": { "S": "value_3" } } }, "col_4": { "BOOL": true } } } } }

NO_UNNEST example

With NO_UNNEST, the entire row is stored within one column plus the primary key. DynamoDB type information is preserved. This maintains compatibility with Redshift querying patterns.

Resulting Iceberg table (assuming col_1 is primary key):

col_1 (string) value (struct)
value_1
{ "col_2": { "M": { "col_3": { "M": { "id": { "S": "value_3" } } }, "col_4": { "BOOL": true } } } }

Queries would need to use struct and array access patterns:

SELECT value.col_1, value.col_2.M.col_3.M.id.S, value.col_2.M.col_4.BOOL FROM product_table;

TOP_LEVEL example

With TOP_LEVEL, only the top-level fields are unnested while keeping nested fields intact as structs. DynamoDB type information is removed and typing is maintained. Converts to string type when schema conflicts occur.

Resulting Glue table after replication:

col_1 (string) col_2 (struct)
value_1
{ "col_3": { "id": "value_3" }, "col_4": true }

Queries would be simplified for the first level:

SELECT col_1, col_2.col_3.id, col_2.col_4 FROM product_table;

FULL example

With FULL unnesting, both top-level fields and nested struct/map fields are flattened. Dot notation is used for nested fields (e.g., "col_2.col_3.id"). Array elements remain unnested. Each leaf node becomes a top-level column.

Resulting Glue table after replication:

col_1 (string) col_2.col_3.id (string) col_2.col_4 (boolean)
value_1 value_3 TRUE

Queries would be fully flattened:

SELECT col_1, "col_2.col_3.id", "col_2.col_4" FROM product_table;