Question

Difficulty: HardData Store Operations with Amazon DynamoDB

A SaaS billing application stores invoice records in an Amazon DynamoDB table. The table has `CustomerId` as the partition key and `InvoiceId` as the sort key. An `InvoiceStatus` attribute indicates whether the invoice is `PAID` or `UNPAID`. Approximately 98%98\% of all invoices are `PAID`. A developer needs to build a dashboard feature that retrieves only the `UNPAID` invoices for a specific customer. Which of the following strategies is the most performant and cost-effective way to retrieve these records?

  1. Create a Global Secondary Index (GSI) with `CustomerId` as the partition key and a new attribute `UnpaidTimestamp` as the sort key, which is only populated when `InvoiceStatus` is `UNPAID`. Query this GSI using the `CustomerId`.Answer
  2. B
    Perform a Scan operation on the base table using a `FilterExpression` to filter items where `CustomerId` matches the target customer and `InvoiceStatus` is `UNPAID`.
  3. C
    Create a Global Secondary Index (GSI) using `InvoiceStatus` as the partition key and `CustomerId` as the sort key. Query this GSI using `InvoiceStatus = UNPAID` and `CustomerId`.
  4. D
    Query the base table using `CustomerId` to retrieve all invoices, filter for `UNPAID` status in the application logic, and initialize the AWS SDK client using hardcoded AWS IAM access keys.

Answer

Creating a sparse Global Secondary Index (GSI) with CustomerId as the partition key and a conditional attribute like UnpaidTimestamp as the sort key, then querying that GSI.
The correct strategy uses a sparse Global Secondary Index (GSI). By defining the GSI with CustomerId as the partition key and a custom attribute (such as UnpaidTimestamp) as the sort key that is only written when the invoice is UNPAID, DynamoDB will only index the unpaid invoices. Since 98% of the invoices are PAID, they will not have the UnpaidTimestamp attribute and will be excluded from the GSI. This minimizes the storage size of the GSI and allows highly efficient, low-cost Query operations restricted to the target customer's unpaid invoices.

Step-by-Step Solution

1
Analyze the query pattern and data distribution.
Unpaid invoices represent only 2% of the dataset, which makes it a sparse subset. The target query needs to retrieve these records for a specific customer.
Understanding data distribution helps choose between a base table query, scan, or secondary index.
2
Evaluate index design options for low-frequency attributes.
A sparse GSI can be created by choosing a sort key attribute (like UnpaidTimestamp) that is only populated when the status is UNPAID. Items without this attribute will not be indexed.
Excluding paid invoices from the index reduces the GSI storage size and ensures that queries against the GSI only read relevant records.
3
Assess partition key cardinality to avoid throttling.
Using CustomerId as the GSI partition key distributes the load across many unique customer partitions, preventing hot partition issues.
If InvoiceStatus was used as the GSI partition key, the 98% of writes for PAID invoices would concentrate on a single partition key value, causing write throttling.

Key Concept

Sparse Global Secondary Indexes (GSIs) for filtering low-cardinality subsets of data.
Rate this question