Самый быстрый способ запроса последних элементов в таблице Azure?

У меня есть таблица Azure, где клиенты отправляют сообщения, в одной таблице могут быть миллионы сообщений. Я хочу найти самый быстрый способ получить сообщения, опубликованные за последние 10 минут (как часто я обновляю веб-страницу). Поскольку индексируется только ключ раздела, я играл с идеей использования даты и времени, когда сообщение было опубликовано как ключ раздела, например строка как формат даты ISO8601, такой как "2009-06-15T13: 45: 30.0900000",

Пример псевдокода:

var message = "Hello word!";
var messagePartitionKey = DateTime.Now.ToString("o");
var messageEntity = new MessageEntity(messagePartitionKey, message);
dataSource.Insert(messageEntity);

а затем запросить сообщения, опубликованные за последние 10 минут, как это (непроверенный псевдо-код снова):

// Get the date and time 10 minutes ago
var tenMinutesAgo = DateTime.Now.Subtract(new TimeSpan(0, 10, 0)).ToString("o");

// Query for the latest messages
var latestMessages = (from t in
   context.Messages
   where t.PartitionKey.CompareTo(tenMinutesAgo) <= 0
   select t
   )

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

Ответ 1

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

Вместо использования DateTime.Now используйте Date.UtcNow. Из того, что я понимаю, экземпляры используют для использования времени Utc в качестве базы в любом случае, но это просто гарантирует, что вы сравниваете яблоки с яблоками, и вы можете надежно преобразовать время обратно в любой часовой пояс, который вы хотите, когда будете показывать их.

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

var messagePartitionKey = (DateTime.MaxValue.Ticks - _contactDate.Ticks).ToString("d19");

Также было бы полезно указать ключ строки. Хотя маловероятно, что два сообщения будут отправлены точно в одно и то же время, это не невозможно. Если у вас нет очевидного ключа строки, просто установите его как Guid.

Ответ 2

Основной ключ для таблицы - это комбинация PartitionKey и RowKey (которая формирует кластеризованный индекс).

В вашем случае просто выберите RowKey вместо ParitionKey (укажите для этого постоянное значение).

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

Ответ 3

Я бы предложил сделать что-то похожее на то, что API-интерфейс Diagnostics делает с WADPerformanceCountersTable. Там PartitionKey группирует несколько временных меток в один элемент. То есть: округляет все временные метки до ближайших нескольких минут (скажем, ближайшие 5 минут). Таким образом, вы не имеете ограниченного количества ключей разделов и все же можете выполнять на них заданные запросы.

Так, например, вы можете иметь PartitionKey, который сопоставляет каждую метку времени, которая округляется до 00:00, 00:05, 00:10, 00:15 и т.д., А затем преобразуется в Ticks

Ответ 4

  • Из моего понимания с использованием ключа раздела с точным равным "=" будет намного быстрее, чем меньше, чем с помощью "<" или "больше чем">.
  • Также убедитесь, что приложите больше усилий, если мы сможем получить уникальную комбинацию ключа раздела и ключа строки для вашего состояния.
  • Также убедитесь, что вы делаете меньше уникальных комбинаций значений ключей разделов, чтобы избежать большего количества разделов.