Учебники

DynamoDB — локальные вторичные индексы

Некоторые приложения выполняют запросы только с первичным ключом, но в некоторых ситуациях используется альтернативный ключ сортировки. Разрешите вашему приложению выбор путем создания одного или нескольких локальных вторичных индексов.

Сложные требования к доступу к данным, такие как объединение миллионов элементов, делают необходимым выполнение более эффективных запросов / сканирований. Локальные вторичные индексы предоставляют альтернативный ключ сортировки для значения ключа раздела. Они также содержат копии всех или некоторых атрибутов таблицы. Они организуют данные по ключу разделения таблицы, но используют другой ключ сортировки.

Использование локального вторичного индекса устраняет необходимость сканирования всей таблицы и позволяет выполнять простой и быстрый запрос с использованием ключа сортировки.

Все локальные вторичные индексы должны удовлетворять определенным условиям —

  • Идентичный ключ раздела и ключ раздела исходной таблицы.
  • Ключ сортировки только одного скалярного атрибута.
  • Проекция исходного ключа сортировки таблицы, действующего как неключевой атрибут.

Все локальные вторичные индексы автоматически содержат ключи разделов и сортировки из родительских таблиц. В запросах это означает эффективный сбор спроецированных атрибутов, а также поиск не спроецированных атрибутов.

Предел хранилища для локального вторичного индекса остается 10 ГБ на значение ключа раздела, которое включает в себя все элементы таблицы и элементы индекса, совместно использующие значение ключа раздела.

Проецирование атрибута

Некоторые операции требуют избыточного чтения / извлечения из-за сложности. Эти операции могут потреблять значительную пропускную способность. Проекция позволяет избежать дорогостоящей выборки и выполнять сложные запросы, изолируя эти атрибуты. Помните, что проекции состоят из атрибутов, скопированных во вторичный индекс.

При создании вторичного индекса вы указываете проецируемые атрибуты. Вспомните три опции, предоставляемые DynamoDB: KEYS_ONLY, INCLUDE и ALL .

Выбирая определенные атрибуты в проекции, учитывайте связанные с этим компромиссы затрат —

  • Если вы проецируете только небольшой набор необходимых атрибутов, вы значительно сократите затраты на хранение.

  • Если вы проектируете часто используемые неключевые атрибуты, вы компенсируете затраты на сканирование с затратами на хранение.

  • Если вы проецируете большинство или все неключевые атрибуты, это максимизирует гибкость и снижает пропускную способность (без поиска); Однако стоимость хранения возрастает.

  • Если вы проектируете KEYS_ONLY для частых записей / обновлений и нечастых запросов, это минимизирует размер, но поддерживает подготовку запросов.

Если вы проецируете только небольшой набор необходимых атрибутов, вы значительно сократите затраты на хранение.

Если вы проектируете часто используемые неключевые атрибуты, вы компенсируете затраты на сканирование с затратами на хранение.

Если вы проецируете большинство или все неключевые атрибуты, это максимизирует гибкость и снижает пропускную способность (без поиска); Однако стоимость хранения возрастает.

Если вы проектируете KEYS_ONLY для частых записей / обновлений и нечастых запросов, это минимизирует размер, но поддерживает подготовку запросов.

Создание локального вторичного индекса

Используйте параметр LocalSecondaryIndex в CreateTable, чтобы создать один или несколько локальных вторичных индексов. Вы должны указать один неключевой атрибут для ключа сортировки. При создании таблицы вы создаете локальные вторичные индексы. При удалении вы удаляете эти индексы.

Таблицы с локальным вторичным индексом должны соответствовать ограничениям в размере 10 ГБ на значение ключа раздела, но могут хранить любое количество элементов.

Локальный вторичный индекс запросов и сканирования

Операция запроса к локальным вторичным индексам возвращает все элементы с совпадающим значением ключа раздела, когда несколько элементов в индексе совместно используют значения ключа сортировки. Соответствующие элементы не возвращаются в определенном порядке. Запросы для локальных вторичных индексов используют либо возможную, либо строгую согласованность, а строго согласованные чтения обеспечивают получение последних значений.

Операция сканирования возвращает все локальные данные вторичного индекса. При сканировании необходимо указать имя таблицы и индекса и разрешить использование выражения фильтра для отбрасывания данных.

Написание предмета

При создании локального вторичного индекса вы указываете атрибут ключа сортировки и его тип данных. Когда вы пишете элемент, его тип должен соответствовать типу данных схемы ключей, если элемент определяет атрибут ключа индекса.

DynamoDB не предъявляет никаких требований к отношениям «один к одному» для элементов таблицы и элементов локального вторичного индекса. Таблицы с несколькими локальными вторичными индексами имеют более высокие затраты на запись, чем таблицы с меньшими.

Вопросы пропускной способности в локальных вторичных индексах

Потребляемая мощность чтения запроса зависит от характера доступа к данным. В запросах используется либо возможная, либо строгая согласованность, при строго согласованных чтениях используется одна единица по сравнению с половиной единиц в конечном итоге согласованных чтений.

Ограничения результата включают максимальный размер 1 МБ. Размеры результата получаются из суммы соответствующего размера элемента индекса, округленной до ближайших 4 КБ, и размера соответствующего элемента таблицы также округленной до ближайших 4 КБ.

Потребляемая мощность записи остается в пределах выделенных единиц. Рассчитайте общую обеспеченную стоимость, найдя сумму потребленных единиц в записи таблицы и потребленных единиц в обновлении индексов.

Вы также можете рассмотреть ключевые факторы, влияющие на стоимость, некоторые из которых могут быть —

  • Когда вы пишете элемент, определяющий индексированный атрибут, или обновляете элемент, чтобы определить неопределенный индексированный атрибут, происходит одна операция записи.

  • Когда обновление таблицы изменяет значение атрибута индексированного ключа, происходит две записи для удаления, а затем — для добавления элемента.

  • Когда запись вызывает удаление индексированного атрибута, происходит одна запись для удаления проекции старого элемента.

  • Если элемент не существует в индексе до или после обновления, запись не производится.

Когда вы пишете элемент, определяющий индексированный атрибут, или обновляете элемент, чтобы определить неопределенный индексированный атрибут, происходит одна операция записи.

Когда обновление таблицы изменяет значение атрибута индексированного ключа, происходит две записи для удаления, а затем — для добавления элемента.

Когда запись вызывает удаление индексированного атрибута, происходит одна запись для удаления проекции старого элемента.

Если элемент не существует в индексе до или после обновления, запись не производится.

Хранение локального вторичного индекса

При записи элемента таблицы DynamoDB автоматически копирует правильный набор атрибутов в требуемые локальные вторичные индексы. Это заряжает ваш аккаунт. Используемое пространство получается из суммы размера байтов первичного ключа таблицы, размера байта атрибута ключа индекса, любого байта текущего размера проецируемого атрибута и накладных расходов 100 байт для каждого элемента индекса.

Хранение оценки получается путем оценки среднего размера элемента индекса и умножения на количество элемента таблицы.

Использование Java для работы с локальными вторичными индексами

Создайте локальный вторичный индекс, сначала создав экземпляр класса DynamoDB. Затем создайте экземпляр класса CreateTableRequest с необходимой информацией запроса. Наконец, используйте метод createTable.

пример

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
String tableName = "Tools";  
CreateTableRequest createTableRequest = new 
   CreateTableRequest().withTableName(tableName);
   
//Provisioned Throughput
createTableRequest.setProvisionedThroughput (
   new ProvisionedThroughput()
   .withReadCapacityUnits((long)5)
   .withWriteCapacityUnits(( long)5));
   
//Attributes 
ArrayList<AttributeDefinition> attributeDefinitions = 
   new ArrayList<AttributeDefinition>();
   attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Make")
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Model")
   .withAttributeType("S"));
   
attributeDefinitions.add(new AttributeDefinition()
   .withAttributeName("Line")
   .withAttributeType("S"));
   
createTableRequest.setAttributeDefinitions(attributeDefinitions);

//Key Schema 
ArrayList<KeySchemaElement> tableKeySchema = new 
   ArrayList<KeySchemaElement>();
   
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                    //Partition key
   
tableKeySchema.add(new KeySchemaElement()
   .withAttributeName("Model")
   .withKeyType(KeyType.RANGE));                   //Sort key
   
createTableRequest.setKeySchema(tableKeySchema);
ArrayList<KeySchemaElement> indexKeySchema = new 
   ArrayList<KeySchemaElement>();
   
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Make")
   .withKeyType(KeyType.HASH));                   //Partition key
   
indexKeySchema.add(new KeySchemaElement()
   .withAttributeName("Line")
   .withKeyType(KeyType.RANGE));                   //Sort key
   
Projection projection = new Projection()
   .withProjectionType(ProjectionType.INCLUDE);

ArrayList<String> nonKeyAttributes = new ArrayList<String>(); 
nonKeyAttributes.add("Type"); 
nonKeyAttributes.add("Year"); 
projection.setNonKeyAttributes(nonKeyAttributes);  

LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex() 
   .withIndexName("ModelIndex")
   .withKeySchema(indexKeySchema)
   .withProjection(p rojection);  

ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new 
   ArrayList<LocalSecondaryIndex>(); 

localSecondaryIndexes.add(localSecondaryIndex); 
createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);  
Table table = dynamoDB.createTable(createTableRequest); 
System.out.println(table.getDescription());

Получить информацию о локальном вторичном индексе с помощью метода description. Просто создайте экземпляр класса DynamoDB, создайте экземпляр класса Table и передайте таблицу методу description.

пример

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
String tableName = "Tools";
Table table = dynamoDB.getTable(tableName);
TableDescription tableDescription = table.describe();

List<LocalSecondaryIndexDescription> localSecondaryIndexes = 
   tableDescription.getLocalSecondaryIndexes();
   
Iterator<LocalSecondaryIndexDescription> lsiIter = 
   localSecondaryIndexes.iterator();
   
while (lsiIter.hasNext()) {  
   LocalSecondaryIndexDescription lsiDescription = lsiIter.next(); 
   System.out.println("Index info " + lsiDescription.getIndexName() + ":"); 
   Iterator<KeySchemaElement> kseIter = lsiDescription.getKeySchema().iterator(); 
   
   while (kseIter.hasNext()) { 
      KeySchemaElement kse = kseIter.next(); 
      System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType()); 
   }
   
   Projection projection = lsiDescription.getProjection(); 
   System.out.println("\tProjection type: " + projection.getProjectionType()); 
   
   if (projection.getProjectionType().toString().equals("INCLUDE")) { 
      System.out.println("\t\tNon-key projected attributes: " + 
         projection.getNonKeyAttributes()); 
   } 
}

Выполните запрос, выполнив те же действия, что и запрос таблицы. Просто создайте экземпляр класса DynamoDB, экземпляр класса Table, экземпляр класса Index, объект запроса и используйте метод запроса.

пример

DynamoDB dynamoDB = new DynamoDB(new AmazonDynamoDBClient( 
   new ProfileCredentialsProvider()));
   
String tableName = "Tools";  
Table table = dynamoDB.getTable(tableName); 
Index index = table.getIndex("LineIndex");  
QuerySpec spec = new QuerySpec() 
   .withKeyConditionExpression("Make = :v_make and Line = :v_line") 
   .withValueMap(new ValueMap() 
   .withString(":v_make", "Depault") 
   .withString(":v_line", "SuperSawz"));
      
ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> itemsIter = items.iterator();

while (itemsIter.hasNext()) { 
   Item item = itemsIter.next(); 
   System.out.println(item.toJSONPretty()); 
}

Вы также можете просмотреть следующий пример.

Примечание. В следующем примере может использоваться ранее созданный источник данных. Прежде чем пытаться выполнить, приобретите вспомогательные библиотеки и создайте необходимые источники данных (таблицы с требуемыми характеристиками или другие ссылочные источники).

В следующем примере также используется Eclipse IDE, файл учетных данных AWS и набор инструментов AWS в Java-проекте Eclipse AWS.