Indexes in DynamoDB make querying the data more efficient and faster than scanning the whole table. There are two types of indexes that can be created in a table, one is the Partition key and the other one is the Sort key. These indexes are used to improve the data access from DynamoDB.
When a new table is created, it is mandatory to select a column as the primary Partition key which will be the table’s default primary key. We can run queries on the table based on this default Partition key. But if we need another key to be added to sort the data or to be added in the queries along with the Partition key, we can also add the Sort key in the primary index. Syntax for adding these indexes in serverless.yml
will be:
TableNameDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: created_at
AttributeType: N
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: created_at
KeyType: RANGE
TableName: ${file(./aws/dynamodb_tables.json):TABLENAME}
The above code creates two indexes in the table, one is id, which is the Partition key and the datatype is going to be string, and the other one is created_at
, which is the Sort key, and the datatype will be Integer.
And then, DynamoDB supports two types of indexes:
- Global Secondary Index
- Local Secondary Index
Global Secondary Indexes(GSIs)
When we define a Global Secondary Index, it creates a separate indexed table, where we can run our queries using the indexes mentioned in the GSI. GSIs have a partition key and a sort key that can be different from the keys in the base table. GSIs can be created on tables with simple key schemas and don’t share throughput for read and write with the base table.
With GSI queries and scans, you can only fetch the attributes that are projected in that particular index. For simplicity, we can consider GSI as a secondary table with the same data which has its own Partition and Sort keys. In serverless.yml
, if we need to add GSI, the code will be like:
TableNameDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: created_at
AttributeType: N
- AttributeName: cat_id
AttributeType: S
- AttributeName: is_deleted
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: created_at
KeyType: RANGE
GlobalSecondaryIndexes:
- IndexName: category_info
KeySchema:
- AttributeName: cat_id
KeyType: HASH
- AttributeName: is_deleted
KeyType: RANGE
Projection:
ProjectionType: "ALL"
TableName: ${file(./aws/dynamodb_tables.json):TABLENAME}
Here we have defined a new Global Secondary Index named category_info
, which has its own Hash and Range keys.
Local Secondary Indexes(LSIs)
LSIs have a partition key that must be the same as the partition key of its table, but the sort key can be any other attribute. Local indexes are only useful for different sorting patterns. Local Indexes can be used to add an extra Sort key to the table along with the Global Secondary Index and also with the base table indexes.
Local indexes limit data volume to 10 GB for any given partition key value.
TableNameDynamoDBTable:
Type: 'AWS::DynamoDB::Table'
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: created_at
AttributeType: N
- AttributeName: is_deleted
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: created_at
KeyType: RANGE
LocalSecondaryIndexes:
- IndexName: is_delete-index
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: is_deleted
KeyType: RANGE
Here we have created an LSI named is_delete-index
, which has the same Partition key id as the base table and is_deleted as the Range key. An LSI lets us query over a single partition, as specified by the partition key value in the query.
Also read about, DynamoDB, When and How to Use.
Learn more about service quotas: AWS DynamoDB Service Quotas