Запрос DynamoDB по дате



Я исхожу из фона реляционной базы данных и пытаюсь работать с DynamoDB amazon



У меня есть таблица с хэш-ключом "DataID" и диапазоном "CreatedAt" и кучей элементов в нем.



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



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



Так что же я делаю не так? Является ли моя схема таблицы неправильной, не должен ли хэш-ключ быть уникальным? или есть другой способ запроса?

658   7  

7 ответов:

Обновленный Ответ:

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

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

подробнее о вторичных индексах DynamoDB смотрите документацию по вторичному индексу

Оригинальный Ответ:

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

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

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

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

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

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

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

лучше всего определить более полезные разделы для создания, чтобы сохранить данные:

  • вам действительно нужно посмотреть на все строки, или это только строки по конкретному пользователь?

  • можно ли сначала сузить список по месяцам и сделать несколько запросов (по одному для каждого месяца)? Или по годам?

  • Если вы делаете анализ временных рядов, есть несколько вариантов, измените ключ раздела на что-то вычисленное на PUT сделать query проще, или использовать другой продукт aws, такой как kinesis, который поддается регистрации только для добавления.

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

Hash Key                 | Range Key
------------------------------------
Date value of CreatedAt  | CreatedAt

ограничение, наложенное на пользователя HTTP API для указания количества дней для получения данных, по умолчанию составляет 24 часа.

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

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

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

|  ID  | DataID | Created | Data |
|------+--------+---------+------|
| hash | xxxxx  | 1234567 | blah |

ваш хэш-ключом является идентификатор Ваш вторичный индекс определяется как: DataID-Created-index (это имя, которое будет использовать DynamoDB)

затем, вы можете сделать запрос, как это:

var params = {
    TableName: "Table",
    IndexName: "DataID-Created-index",
    KeyConditionExpression: "DataID = :v_ID AND Created > :v_created",
    ExpressionAttributeValues: {":v_ID": {S: "some_id"},
                                ":v_created": {N: "timestamp"}
    },
    ProjectionExpression: "ID, DataID, Created, Data"
};

ddb.query(params, function(err, data) {
    if (err) 
        console.log(err);
    else {
        data.Items.sort(function(a, b) {
            return parseFloat(a.Created.N) - parseFloat(b.Created.N);
        });
        // More code here
    }
});

по существу ваш запрос выглядит так:

SELECT * FROM TABLE WHERE DataID = "some_id" AND Created > timestamp;

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

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

вы можете сделать хэш-ключ чем-то вроде идентификатора "категории продукта", а затем ключ диапазона как комбинацию метки времени с уникальным идентификатором, добавленным в конце. Таким образом, вы знаете хэш-ключ и все еще можете запросить дату с большим, чем.

вы можете иметь несколько одинаковых хэш-ключей, но только если у вас есть ключевой диапазон, который варьируется. Думайте о нем, как форматы файлов, вы можете иметь 2 файла с тем же именем в той же папке, пока их формат отличается. Если их формат одинаков, их имя должно быть другим. Та же концепция применяется к ключам хэша/диапазона DynamoDB; просто подумайте о хэше как о имени и диапазоне как о формате.

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

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

Я по-прежнему рекомендую ответ Майка Бранта в качестве предпочтительного метода использования DynamoDB; и используйте этот метод сам. В моем случае у меня просто есть центральная таблица с только хэш-ключом в качестве моего идентификатора, затем вторичные таблицы, которые имеют хэш и диапазон, который можно запросить, а затем элемент указывает код на "элемент интереса" центральной таблицы напрямую.

дополнительные данные о вторичных индексах можно найти в документации Amazon DynamoDB здесь для тех, кто заинтересован.

в любом случае, надеюсь, это поможет кому-либо еще, что происходит в этой теме.

Обновил Ответ Нет удобного способа сделать это с помощью запросов Dynamo DB с предсказуемой пропускной способностью. Один (суб оптимальный) вариант-использовать GSI с искусственным HashKey & CreatedAt. Затем запросите только HashKey и упомяните ScanIndexForward, чтобы упорядочить результаты. Если вы можете придумать естественный хэш-ключ (скажем, категория элемента и т. д.), то этот метод является победителем. С другой стороны, если вы сохраняете один и тот же хэш-ключ для всех элементов, то это повлияет на пропускную способность в основном, когда ваш набор данных растет за пределами 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

Comments

    Ничего не найдено.