0
0
DynamodbHow-ToBeginner · 4 min read

How to Design Access Patterns in DynamoDB for Efficient Queries

To design access patterns in DynamoDB, start by identifying all the ways your application will query data and model your table keys accordingly using Partition Keys and Sort Keys. Use Global Secondary Indexes (GSI) and Local Secondary Indexes (LSI) to support additional query patterns without scanning the entire table.
📐

Syntax

DynamoDB access patterns rely on defining keys and indexes to efficiently retrieve data.

  • Partition Key: The main key used to distribute data across partitions.
  • Sort Key: Optional key to sort and filter data within a partition.
  • Global Secondary Index (GSI): Allows querying on non-primary key attributes across all partitions.
  • Local Secondary Index (LSI): Allows querying on alternate sort keys within the same partition key.
sql
CREATE TABLE ExampleTable (
  UserId STRING,
  OrderId STRING,
  OrderDate STRING,
  Status STRING,
  PRIMARY KEY (UserId, OrderId)
);

-- Note: GSIs are created separately in DynamoDB and not in the CREATE TABLE statement like in SQL.
💻

Example

This example shows a DynamoDB table designed for an e-commerce app where users have orders. The primary key uses UserId as the partition key and OrderId as the sort key. A GSI is created to query orders by Status and OrderDate.

python
import boto3

# Create DynamoDB client
client = boto3.client('dynamodb')

# Create table with primary key and GSI
client.create_table(
    TableName='Orders',
    KeySchema=[
        {'AttributeName': 'UserId', 'KeyType': 'HASH'},  # Partition key
        {'AttributeName': 'OrderId', 'KeyType': 'RANGE'}  # Sort key
    ],
    AttributeDefinitions=[
        {'AttributeName': 'UserId', 'AttributeType': 'S'},
        {'AttributeName': 'OrderId', 'AttributeType': 'S'},
        {'AttributeName': 'Status', 'AttributeType': 'S'},
        {'AttributeName': 'OrderDate', 'AttributeType': 'S'}
    ],
    GlobalSecondaryIndexes=[
        {
            'IndexName': 'StatusOrderDateIndex',
            'KeySchema': [
                {'AttributeName': 'Status', 'KeyType': 'HASH'},
                {'AttributeName': 'OrderDate', 'KeyType': 'RANGE'}
            ],
            'Projection': {'ProjectionType': 'ALL'},
            'ProvisionedThroughput': {'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5}
        }
    ],
    ProvisionedThroughput={'ReadCapacityUnits': 5, 'WriteCapacityUnits': 5}
)

print('Table creation initiated.')
Output
Table creation initiated.
⚠️

Common Pitfalls

Common mistakes when designing access patterns in DynamoDB include:

  • Using only a partition key without a sort key when multiple query patterns require sorting or filtering.
  • Not planning for all query types upfront, leading to inefficient scans later.
  • Overusing GSIs which can increase costs and complexity.
  • Ignoring item size and hot partition issues by uneven key distribution.

Always model your data based on how your app queries it, not just how it looks.

sql
/* Wrong: Single partition key without sort key limits query flexibility */
CREATE TABLE Orders (
  OrderId STRING,
  Status STRING,
  PRIMARY KEY (OrderId)
);

/* Right: Use partition and sort keys to support multiple queries */
CREATE TABLE Orders (
  UserId STRING,
  OrderId STRING,
  PRIMARY KEY (UserId, OrderId)
);
📊

Quick Reference

ConceptPurposeWhen to Use
Partition KeyDistributes data across partitionsAlways required for table design
Sort KeySorts and filters items within a partitionWhen you need ordered or filtered queries
Global Secondary Index (GSI)Supports alternate query patterns across partitionsFor queries on non-primary key attributes
Local Secondary Index (LSI)Supports alternate sort keys within the same partitionWhen you want multiple sort keys per partition

Key Takeaways

Design your DynamoDB table keys based on all expected query patterns before implementation.
Use partition and sort keys to efficiently organize and retrieve data.
Add GSIs and LSIs only to support additional query needs without scanning the table.
Avoid hot partitions by choosing keys that distribute traffic evenly.
Plan your access patterns early to reduce costly redesigns and scans.