Хранилище таблиц Azure — выбор ключа раздела и строки для использования между запросами

#performance #azure #azure-table-storage

#Производительность #azure #azure-table-storage

Вопрос:

Я полный новичок в Azure! Цель состоит в том, чтобы возвращать строки на основе метки времени, хранящейся в RowKey. Поскольку с каждым запросом связана транзакционная стоимость, я хочу минимизировать количество транзакций / запросов при сохранении производительности

Это предлагаемые ключи раздела и строки:

  • Ключ раздела: TextCache_(AccountId)_(ParentMessageId)
  • Ключ строки: (DateOfMessage)_(MessageId)

Легенда:

  • AccountId — это целое число
  • ParentMessageId — родительский MessageId, если он есть, пустой, если он родительский
  • DateOfMessage — Дата создания сообщения — формат будет DateTime.Отметки.toString(«d19»)
  • MessageId — уникальный идентификатор сообщения

Я хотел бы получить обратно из одного запроса строки и любые дочерние элементы, которые > или < DateOfMessage_MessageId

Можно ли это сделать с помощью предложенных мной PartitionKeys и RowKeys?

ie .. (в псевдокоде)

 var results = ctx.PartitionKey.StartsWith(TextCache_AccountId) 
   amp;amp; ctx.RowKey > (TimeStamp)_MessageId
  

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

ie .. (в псевдокоде)

 var results = ( 
      ( 
        ctx.PartitionKey.StartsWith(TextCache_(AccountId1)) amp;amp; 
            amp;amp; ctx.RowKey > (TimeStamp1)_MessageId1 )
      )
      ||
      ( 
        ctx.PartitionKey.StartsWith(TextCache_(AccountId2)) amp;amp; 
            amp;amp; ctx.RowKey > (TimeStamp2)_MessageId2 )
      ) ... 
          )
         .Take(10)
  

Ответ №1:

Краткий ответ на ваши вопросы — да, но есть некоторые вещи, на которые вам нужно обратить внимание.

Хранилище таблиц Azure не имеет прямого эквивалента .StartsWith() . Если вы используете библиотеку хранилища в сочетании с LINQ, вы можете использовать .CompareTo() (> и < не переводите должным образом), что будет означать, что если вы запустите поиск для учетной записи 1 и попросите запрос вернуть 1000 результатов, но для учетной записи 1 есть только 600 результатов, последние 400 результатов будут для учетной записи 10 (следующий номер учетной записи в лексическом смысле). Итак, вам нужно быть немного умнее в том, как вы обрабатываете свои результаты.

Если бы вы дополнили идентификатор учетной записи начальными 0, вы могли бы сделать что-то вроде этого (здесь также используется псевдокод)

 ctx.PartionKey > "TextCache_0000000001"
amp;amp; ctx.PartitionKey < "TextCache_0000000002"
amp;amp; ctx.RowKey > "123465798"
  

Следует иметь в виду еще кое-что, что запросы к таблицам Azure возвращают свои результаты в PartitionKey том RowKey порядке. Таким образом, в вашем случае сообщения без ParentMessageId будут возвращены перед сообщениями с ParentMessageId . Если вы никогда не собираетесь запрашивать эту таблицу с помощью ParentMessageId , я бы перенес это в свойство.

Если TextCache_ это просто строковая константа, она ничего не добавляет, будучи включенной в PartitionKey , если только это действительно не будет что-то значить для вашего кода, когда оно будет возвращено.

Пока вы выполняете второй запрос, я не думаю, что он выдаст то, что вам нужно. Если вы хотите, чтобы первые десять строк располагались в DateOfMessage порядке, то это не сработает (см. Мой пункт выше о порядке сортировки). Если вы выполнили этот запрос как есть, и у учетной записи 1 было 11 сообщений, он вернет только первые 10 сообщений, связанных с учетной записью 1, независимо от того, было ли у учетной записи 2 более раннее сообщение.

Хотя попытка минимизировать количество используемых вами транзакций является хорошей практикой, не стоит слишком беспокоиться об этом. Стоимость запуска ваших рабочих / веб-ролей уменьшит ваши транзакционные издержки. 1 000 000 транзакций обойдутся вам в 1 доллар, что меньше, чем стоимость запуска одного небольшого экземпляра в течение 9 часов.

Комментарии:

1. Спасибо knightpfhor, меня больше заботило достижение скорости 500 транзакций в секунду в хранилище таблиц, что привело бы к регулированию. Я не подумал о заполнении идентификатора учетной записи, которое определенно потребуется. Проведем некоторое тестирование

2. Стоит отметить, что ограничение дроссельной заслонки для каждого раздела, а не глобальное (хотя глобальное ограничение составляет несколько тысяч транзакций в секунду

3. Что касается TextCache_ , я добавил это в качестве идентификатора таблицы. Если у меня есть несколько объектов, как мне их различать?

4. Вы имеете в виду, что у вас есть несколько типов объектов, которые вы пытаетесь сохранить в одной таблице?

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