Я исхожу из фона реляционной базы данных и пытаюсь работать с DynamoDB от Amazon
У меня есть таблица с хэш-ключом «DataID» и диапазоном «CreatedAt» и кучей элементов в ней.
Я пытаюсь получить все элементы, созданные после определенной даты и отсортированные по дате. Что довольно просто в реляционной базе данных.
В DynamoDB самое близкое, что я смог найти, - это запрос и использование ключа диапазона больше, чем фильтр. Единственная проблема заключается в том, что для выполнения запроса мне нужен хеш-ключ, который противоречит цели.
Так что я делаю не так? Моя схема таблицы неправильная, не должен ли хеш-ключ быть уникальным? или есть другой способ сделать запрос?
CreatedAt
точкой больше определенной.Учитывая вашу текущую структуру таблицы, в DynamoDB это невозможно. Огромная проблема состоит в том, чтобы понять, что хеш-ключ таблицы (раздела) следует рассматривать как создание отдельных таблиц. В некотором смысле это действительно мощно (подумайте о ключах разделов как о создании новой таблицы для каждого пользователя или клиента и т. Д.).
Запросы можно выполнять только в одном разделе. Это действительно конец истории. Это означает, что если вы хотите запросить по дате (вы захотите использовать msec с эпохи), тогда все элементы, которые вы хотите получить в одном запросе, должны иметь один и тот же хэш (ключ раздела).
Я должен уточнить это. Вы абсолютно можете
scan
по критерию, который вы ищете, это не проблема, но это означает, что вы будете просматривать каждую отдельную строку в своей таблице, а затем проверять, имеет ли эта строка дату, соответствующую вашим параметрам. Это действительно дорого, особенно если вы занимаетесь хранением событий по дате в первую очередь (т.е. у вас много строк).У вас может возникнуть соблазн поместить все данные в один раздел для решения проблемы, и вы абсолютно можете это сделать, однако ваша пропускная способность будет очень низкой, учитывая, что каждый раздел получает только часть от общего установленного количества.
Лучше всего определить более полезные разделы, которые нужно создать для сохранения данных:
Вам действительно нужно просматривать все строки, или это только строки конкретного пользователя?
Можно ли сначала сузить список по месяцам и выполнить несколько запросов (по одному на каждый месяц)? Или по году?
Если вы выполняете анализ временных рядов, есть несколько вариантов: изменить ключ раздела на что-то вычисленное,
PUT
чтобы упроститьquery
задачу, или использовать другой продукт aws, например kinesis, который позволяет вести журнал только с добавлением.источник
yyyy
и хэш, но также создайтеcreated
дату, которую вы можете использовать в качестве ключа диапазона. Затем вы получаете 10 ГБ данных в год (27 МБ в день), что, вероятно, будет достаточно для других обстоятельств. Это означает, что вам нужно создавать запрос в год, когда запросы даты выходят за границу года, но, по крайней мере, это будет работать и безопаснее, чем создание фиктивного хеш-ключа.Подход, который я использовал для решения этой проблемы, заключается в создании глобального вторичного индекса, как показано ниже. Не уверен, что это лучший подход, но надеюсь, будет ли он кому-то полезен.
На пользователя HTTP API накладывается ограничение на указание количества дней для извлечения данных, по умолчанию - 24 часа.
Таким образом, я всегда могу указать HashKey как текущий день даты, а RangeKey может использовать операторы> и <при извлечении. Таким образом, данные также распределяются по нескольким шардам.
источник
Ваш хеш-ключ (первичный для сортировки) должен быть уникальным (если у вас нет диапазона, как указано другими).
В вашем случае для запроса вашей таблицы у вас должен быть вторичный индекс.
Ваш хеш-ключ - это идентификатор. Ваш вторичный индекс определяется как: DataID-Created-index (это имя, которое будет использовать DynamoDB)
Затем вы можете сделать такой запрос:
По сути, ваш запрос выглядит так:
Вторичный индекс увеличит требуемые единицы емкости чтения / записи, поэтому вам нужно это учитывать. Это по-прежнему намного лучше, чем сканирование, которое требует больших затрат по чтению и по времени (и, как мне кажется, ограничивается 100 элементами).
Возможно, это не лучший способ сделать это, но для тех, кто привык к RD (я также привык к SQL), это самый быстрый способ стать продуктивным. Поскольку в отношении схемы нет ограничений, вы можете создать что-то, что работает, и как только у вас появится пропускная способность для работы наиболее эффективным способом, вы можете все изменить.
источник
Вы можете сделать ключ Hash чем-то вроде идентификатора «категории продукта», а затем ключ диапазона как комбинацию отметки времени с уникальным идентификатором, добавленным в конце. Таким образом, вы знаете хэш-ключ и можете запросить дату с числом больше.
источник
У вас может быть несколько одинаковых хеш-ключей; но только если у вас есть ключ диапазона, который меняется. Думайте об этом как о форматах файлов; вы можете иметь 2 файла с одинаковыми именами в одной папке, если их формат различается. Если их формат такой же, их имена должны быть разными. Та же концепция применима к ключам хэша / диапазона DynamoDB; просто воспринимайте хэш как имя, а диапазон - как формат.
Кроме того, я не помню, были ли они у них во время OP (я не верю, что они были), но теперь они предлагают локальные вторичные индексы.
Насколько я понимаю, теперь он должен позволить вам выполнять желаемые запросы без необходимости выполнять полное сканирование. Обратной стороной является то, что эти индексы должны быть указаны при создании таблицы, а также (я считаю) не могут быть пустыми при создании элемента. Кроме того, они требуют дополнительной пропускной способности (хотя обычно не такой большой, как сканирование) и хранилища, поэтому для некоторых это не идеальное решение, а реальная альтернатива.
Однако я все же рекомендую ответ Майка Бранта как предпочтительный метод использования DynamoDB; и сам использую этот метод. В моем случае у меня просто центральная таблица с только хеш-ключом в качестве моего идентификатора, затем вторичные таблицы с хешем и диапазоном, которые можно запросить, затем элемент указывает код на "интересующий элемент" центральной таблицы, напрямую .
Дополнительные данные о вторичных индексах можно найти в документации Amazon DynamoDB здесь. для заинтересованных.
В любом случае, надеюсь, это поможет всем, кто встречается в этой теме.
источник
Обновленный ответ Нет удобного способа сделать это с помощью Dynamo DB Queries с предсказуемой пропускной способностью. Один (неоптимальный) вариант - использовать GSI с искусственным HashKey и CreatedAt. Затем запросите только HashKey и укажите ScanIndexForward, чтобы упорядочить результаты. Если вы можете придумать естественный HashKey (например, категорию элемента и т. Д.), То этот метод является победителем. С другой стороны, если вы сохраните один и тот же HashKey для всех элементов, это повлияет на пропускную способность в основном, когда ваш набор данных вырастет за пределы 10 ГБ (один раздел).
Исходный ответ: теперь это можно сделать в DynamoDB с помощью GSI. Сделайте поле «CreatedAt» как GSI и выполните такие запросы, как (GT some_date). Сохраните дату в виде числа (мсек с эпохи) для такого рода запросов.
Подробности доступны здесь: Глобальные вторичные индексы - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Using
Это очень мощная функция. Имейте в виду, что запрос ограничен (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) Условием - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html
источник
CreatedAt
должен быть ключ диапазона GSI, тогда вам нужно будет выбрать хэш-ключ - и тогда вы вернетесь туда, откуда начали, потому что вы сможете запрашивать GTCreatedAt
только для определенного значения хэш-ключ.