Запросить все элементы с первичным ключом в заданном диапазоне и вторичным ключом, соответствующим заданному значению - PullRequest
0 голосов
/ 12 мая 2019

У меня есть таблица DynamoDB, в которой хранятся предложения.Каждое предложение имеет первичный ключ с именем «id» (типа int) и другие вторичные ключи для каждого слова в предложении.

Например, запись "hello world" будет иметь некоторое целое число в качестве идентификатора и будет иметь записи "hello" = 1 и "world" = 1.Мне нужно запросить все предложения, которые имеют идентификатор в данном диапазоне и которые содержат слово из списка заданных слов (words = [word1, word2, word3, word4, word5]).На данный момент у меня есть следующий запрос:

while items == []:
      response = lyric_table.scan(
                          FilterExpression=(Key(words[0]).eq(1) | 
                                            Key(words[1]).eq(1) | 
                                            Key(words[2]).eq(1) | 
                                            Key(words[3]).eq(1)| 
                                            Key(words[4]).eq(1)) & 
                                            filt,
                          ExclusiveStartKey={'id': r},)
      items = response['Items']

, где

filt = Key('id').between(r1, r2) | Key('id').between(r3, r4) ...

Я также выбираю ExclusiveStartKey в качестве случайного числа, выбранного из r1, r3, ... в каждой итерациицикла while, хотя я не уверен, что это необходимо.

Этот код работает, как и ожидалось, когда «слова» содержат слова, которые встречаются в таблице относительно часто, но для их запуска требуется слишком много времени.когда «слова» содержат слова, которые не слишком часто встречаются в базе данных.В некоторых случаях сканирование выполняется бесконечно.Я также попытался использовать запрос вместо сканирования, но мне не повезло в улучшении кода.

Есть ли у вас какие-либо предложения по оптимизации приведенного выше кода?

1 Ответ

0 голосов
/ 13 мая 2019

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

Если я правильно понимаю ваш вопрос, ваши данные будут выглядеть примерно так:

Id Word SomeValue 101 Hello 1 101 World 2

Если вам известен полный диапазон ваших идентификаторов (скажем, 1-1000), одно из решений может заключаться в том, чтобы объединить эти идентификаторы, использовать ключ сегмента в качестве ключа раздела и идентификатор в качестве ключа сортировки:

BucketId Id 1 .. 1 .. 100 101 100 101 100 121 … 200 300 : 1000

И затем для диапазона (101, 320) вы можете выполнить 3 запроса с идентификаторами 100, 200 и 300 с соответствующими выражениями фильтра. Это определенно будет намного эффективнее, чем сканирование таблицы. Что касается слов, не уверен, каков ваш конкретный вариант использования, но если их количество ограничено для каждого идентификатора, они могут быть сохранены как одна карта или заданный атрибут.

...