Предложения по повышению производительности запросов к хранилищу таблиц Azure - PullRequest
0 голосов
/ 27 июня 2018

У нас есть таблица в хранилище таблиц Azure, которая в настоящее время содержит 50 000 элементов с момента ее новой реализации.

PartitionKey : значение DateTime в виде строки
RowKey: числовое значение в виде строки

Мы используем TableQuery для генерации условия фильтра. Фильтр PartitionKey выглядит примерно так: PartitionKey ge '201801240000000000' && "PartitionKey lt '201806220000000000'"

К сожалению, мы не можем использовать фильтр RowKey, потому что нам нужны данные между двумя датами.

Чтобы получить данные за месяц, потребуется около 5 секунд. И чтобы получить около 3 месяцев, требуется больше времени.

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

Буду признателен за любые предложения по улучшению производительности.

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Ответ Риквдбоша точен.

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

  • Thread-1 => PartitionKey ge '20180601' && PartitionKey lt '20180605'
  • Thread-2 => PartitionKey ge '20180605' && PartitionKey lt '20180610'
  • Thread-3 => PartitionKey ge '20180610' && PartitionKey lt '20180615'
  • Thread-4 => PartitionKey ge '20180615' && PartitionKey lt '20180620'
  • Thread-5 => PartitionKey ge '20180620' && PartitionKey lt '20180725'
  • Thread-6 => PartitionKey ge '20180625' && PartitionKey lt '20180701'

Более того, можно быть еще более агрессивным и параллельно читать меньшие разделы (например, ежедневно) без использования конструкций TableQuery.

Обратите внимание, что ни один из подходов, описанных выше, не обрабатывает стратегию разделения, которая является крайне несбалансированной Например, предположим, что 95% данных за июнь / 2018 г. хранятся в диапазоне от «20180605» до «20180610» или в течение одного дня, может наблюдаться или не наблюдаться улучшение общего времени выполнения по сравнению с последовательным считыванием в этот случай, особенно из-за издержек параллелизма (например, потоков, выделения памяти, синхронизации и т. д.).

Теперь при условии, что это приложение .NET, работающее в ОС Windows, и описанный выше подход подходит для вашего сценария , рассмотрим:

  • Увеличение максимального количества соединений;
  • Отключение алгоритма Nagle;

Найдите ниже фрагмент кода для изменения в конфигурации приложения. Обратите внимание, что:

  • Можно определить адрес (например, https://stackoverflow.com) для maxconnection вместо использования "*" .
  • Рекомендуется запускать тесты производительности, чтобы определить, какая конфигурация подходит для maxconnection, перед выпуском в эксплуатацию.

Более подробную информацию об управлении соединениями можно получить по https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/network/connectionmanagement-element-network-settings.

0 голосов
/ 27 июня 2018

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

  • A Точечный запрос является наиболее эффективным поиском, который рекомендуется использовать, и его рекомендуется использовать для поисков с большим объемом или поисков, требующих минимальной задержки. Такой запрос может использовать индексы для очень эффективного определения местоположения отдельной сущности путем указания значений PartitionKey и RowKey. Например: $ filter = (PartitionKey eq 'Sales') и (RowKey eq '2')
  • Вторым лучшим является Range Query , который использует PartitionKey и фильтрует диапазон значений RowKey, чтобы вернуть более одного объекта. Значение PartitionKey идентифицирует конкретный раздел, а значения RowKey идентифицируют подмножество сущностей в этом разделе. Например: $ filter = PartitionKey eq 'Sales' и RowKey ge 'S' и RowKey lt 'T'
  • Третьим лучшим является Сканирование разделов , которое использует PartitionKey и фильтрует другое неключевое свойство и может возвращать более одного объекта. Значение PartitionKey идентифицирует конкретный раздел, а значения свойств выбираются для подмножества сущностей в этом разделе. Например: $ filter = PartitionKey eq 'Sales' и LastName eq 'Smith'
  • A Сканирование таблицы не включает PartitionKey и является очень неэффективным, поскольку ищет все разделы, которые составляют вашу таблицу, по очереди на предмет соответствия. Он будет выполнять сканирование таблицы независимо от того, использует ли ваш фильтр RowKey. Например: $ filter = LastName eq 'Jones'
  • Запросы, которые возвращают несколько объектов, возвращают их, отсортированные в порядке PartitionKey и RowKey. Чтобы избежать обращения к сущностям в клиенте, выберите RowKey, который определяет наиболее распространенный порядок сортировки.

Источник: Руководство по проектированию таблиц хранения Azure: проектирование масштабируемых и производительных таблиц

Еще одна очень полезная статья: Для чего предназначены PartitionKey и RowKey в Windows Azure Table Storage , особенно если посмотреть на это изображение:

В зависимости от размера и загруженности раздела, разделение распределяется между машинами. Всякий раз, когда раздел получает высокую нагрузку или увеличивается в размерах, управление хранилищем Windows Azure может запустить и переместить раздел на другой компьютер: Partitioning

Edit:
Если вы хотите запросить данные несколькими способами, подумайте о том, чтобы сохранить их несколькими способами. Тем более, что хранение дешево, хранение данных несколько раз не так уж плохо. Таким образом, вы оптимизируете для чтения. Это то, что известно как шаблон Materialized View , который может «помочь поддерживать эффективные запросы и извлечение данных и повысить производительность приложений».

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

...