Запрос для диапазона дат, когда дата является единственным ключом - PullRequest
0 голосов
/ 22 января 2020

Я хочу использовать DynamoDB для хранения исторических значений закрытия запасов. В моем магазине будет несколько запасов, и их количество будет увеличиваться по мере изменения требований. Я полагал, что у меня будет одна таблица, где единственным ключом является "DATE", отформатированный как YYYY-MM-DD.

. Это означает, что у каждого элемента в таблице будет ключ date и несколько атрибутов формы { TICKER = CLOSING_VALUE }

Запросы на определенную дату также будут фильтроваться по подмножеству желаемых биржевых тикеров, например ["INTC", "AAPL"].

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

Как выполнить запрос для получения подмножества биржевых тикеров для заданного диапазона дат?


Обновление :

Я создаю таблицу с ...

{
  AttributeDefinitions: [
    {
      AttributeName: Date,
      AttributeType: S
    }
  ],
  TableName: "Historic",
  KeySchema: [
    {
      AttributeName: Date,
      KeyType: HASH
    }
  ]
}

И запрос:

    {
        table_name: "Historic",
        projection_expression: "USD,CAD",
        filter_expression: "#k between :val1 and :val2",
        expression_attribute_names: { "#k" => "Date" },
        expression_attribute_values: {
            ":val1" => "2019-12-01",
            ":val2" => "2020-01-10"
        }
    }

И я получаю ошибку: Aws::DynamoDB::Errors::ValidationException: Either the KeyConditions or KeyConditionExpression parameter must be specified in the request.

1 Ответ

1 голос
/ 23 января 2020

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

«Ключ разделения» также вызывается в операции CreateTable как «ключ ha sh» - и это действительно так. работает как ключ в таблице ha sh: DynamoDB запускает функцию ha sh для этого ключа и, используя полученное число, решает, какой узел (ы) его большого кластера должен содержать этот раздел. Этот подход позволяет распределить таблицу по кластеру, но делает невозможным 1008 * эффективное извлечение различных разделов, упорядоченных по их ключу. Операция «Сканирование» вернет разделы в, казалось бы, случайном порядке (они, вероятно, будут отсортированы по функции ha sh их ключа), и невозможно эффективно сканировать только диапазон ключей раздела. Это можно сделать неэффективно - отсканировав всю таблицу и отфильтровав только нужные вам разделы. Если я правильно понимаю, это то, что вы пытались сделать. Но это имеет смысл только для крошечных баз данных - это ваш случай?

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

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

Если у вас большое количество акций, но типичный запрос запрашивает только несколько акций, наиболее разумным подходом является использовать имя запаса в качестве ключа раздела, а данные, как я уже сказал, в качестве ключа сортировки. Это позволит вам эффективно Query диапазон дат для одной конкретной акции - и если вам нужно 3 разных акции, вам нужно будет сделать 3 Query с (вы можете и должны делать их параллельно!), Но каждый из эти запросы будут эффективными, и вы будете платить только за фактические данные, которые вы получите, без какой-либо пост-фильтрации.

Если существует огромное количество различных дат (например, вы сохраняете данные с разрешением 1 секунда) ), ваши разделы могут вырасти огромными, и по разным причинам это не рекомендуется. В таком случае вы можете разделить каждый раздел на несколько разделов по некоторому грубому временному окну. Например, вместо одного огромного раздела для запаса «GOOG» используйте один раздел «GOOG Nov 2019», один «GOOG De c 2019» и т. Д. c. Когда вы запрашиваете небольшой диапазон дат, вы узнаете, с какого конкретного раздела c вам нужно читать. Но когда запрос охватывает более одного месяца, вам нужно запросить несколько таких разделов. Обратите внимание, что очень большие запросы будут считывать (и возвращать) огромные объемы данных, поэтому будут очень дорогими, так что вы, вероятно, захотите делать это только в больших аналитических c заданиях.

...