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