Вызывают ли предикаты запроса таблицы Azure "ИЛИ" сканирование?

Предположим следующий запрос:

PartitionKey == 1 И (RowKey == A ИЛИ RowKey == B)

или даже это:

(PartitionKey == 1 И RowKey == A) ИЛИ (PartitionKey == 2 И RowKey == B)

Приводит ли что-нибудь из этого к сканированию?

Я спрашиваю, потому что этот разговор PDC показывает, что это действительно так:

https://channel9.msdn.com/Events/PDC/PDC09/SVC09

В частности, в 27:30 динамик и слайд:

Предикаты "ИЛИ" для ключей => без оптимизации запроса => результаты в сканировании

Это повторяется снова в 29:30, и рекомендуется использовать параллельные запросы. После поиска в Интернете я также нашел эту ветку:

https://social.msdn.microsoft.com/forums/azure/en-us/d7765773-74b8-4860-b07c-b9731a2210c7/performance-of-range-queries-on-partition-keys-and-row-keys

Операция «ИЛИ» в запросах в настоящее время не оптимизирована, но, как я упоминал выше, у нас были запросы на эту функцию.

Сейчас всей этой информации 7-8 лет и, возможно, она изменилась. Предыдущая ссылка указывает на то, что это был запрос функции, и сегодня это могло произойти. Есть это?

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

Рассмотрим сценарий, в котором кто-то пытается получить сотни или тысячи объектов, где заранее известен только Partition + RowKey каждого объекта. Быстрее ли выполнить отдельный запрос для параллельной выборки каждой сущности или использовать предикат «ИЛИ» для пакетной обработки нескольких запросов на вызов, чтобы минимизировать количество параллельных запросов?

Последний вопрос: есть ли какие-либо последствия для производительности при извлечении нескольких сущностей из разных разделов в одном запросе (второй пример запроса вверху вопроса)? Или лучше оставить запрос в одном разделе (1-й пример запроса вверху вопроса)? Обсуждение PDC во время 25:20, кажется, указывает на то, что на самом деле лучше заставить запросы распределять работу по нескольким разделам, чтобы работа могла выполняться параллельно. Однако обсуждение напрямую касалось диапазона запросов по разделам, а не использования предиката «ИЛИ» для двух отдельных разделов.

Спасибо!

** РЕДАКТИРОВАТЬ **

Решил сам проверить работоспособность. Для теста я создал таблицу с одним разделом и миллионом сущностей. Ключ раздела был «0», а ключ строки - значение, увеличивающееся от «0» до «999999».

При запуске теста я сделал:

ServicePointManager.DefaultConnectionLimit = 1000;
servicePoint.UseNagleAlgorithm = false;
servicePoint.Expect100Continue = false;

В первом тесте я построил единственный запрос, который выглядел так:

(PK уравнение '0' и РК уравнение '0') или (PK уравнение '0' и РК уравнение '500') или ... x400

Всего было 400 групп «ИЛИ». Ключ строки был увеличен на 500, чтобы немного разложить запрос.

Для выполнения этого запроса потребовалось Azure 3:26.

Затем я протестировал, используя более сжатую форму того же запроса:

PK экв '0' и (РК экв '0' или РК экв '500' или ... x400)

Снова было всего 400 выражений OR'd. И снова ключ строки был увеличен на 500, чтобы немного разложить запрос.

Для выполнения этого запроса потребовалось Azure 1:19. Лучшее, но все еще совершенно неприемлемое исполнение.

Наконец, я протестировал 400 параллельных запросов с помощью TableOperation.Retrieve ‹>.

В среднем Azure требовалось всего 3 секунды для параллельного выполнения всех этих запросов.

Очевидно, что никогда не используйте «ИЛИ» в выражении и всегда используйте параллельные запросы. ИМО, производительность «ИЛИ» неприемлема, и Microsoft следует просто удалить его, если они не будут его оптимизировать.


person Agendum    schedule 14.05.2017    source источник


Ответы (1)


PartitionKey == 1 И (RowKey == A ИЛИ RowKey == B) Приводит ли какое-либо из этих действий к сканированию?

Да, будет сканирование.

Сервер Azure будет рассматривать этот запрос как сканирование раздела. Он просканирует раздел, равный «1».

(PartitionKey == 1 И RowKey == A) ИЛИ (PartitionKey == 2 И RowKey == B) Приводит ли какое-либо из этих действий к сканированию?

Сервер Azure будет рассматривать этот запрос как сканирование таблицы. Он просканирует всю таблицу и найдет ключ раздела.

Рассмотрим сценарий, в котором вы пытаетесь получить сотни или тысячи сущностей, где заранее известен только Partition + RowKey каждой сущности. Быстрее ли выполнить отдельный запрос для параллельной выборки каждой сущности или использовать предикат «ИЛИ» для пакетной обработки нескольких запросов на вызов, чтобы минимизировать количество параллельных запросов?

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

Есть ли какие-либо последствия для производительности при выборке нескольких сущностей из разных разделов в одном запросе (второй пример запроса вверху вопроса)?

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

Или лучше оставить запрос в одном разделе (1-й пример запроса вверху вопроса)?

Насколько мне известно, скорость сканирования таблицы следующая:

Точечный запрос (один ключ раздела и ключ строки)> Запрос диапазона (один ключ раздела и диапазон ключей строки)> Сканирование раздела (один ключ раздела и диапазон свойств)> Сканирование таблицы (не включая ключ раздела)

Так что лучше хранить запрос в одном разделе.

person Brando Zhang    schedule 15.05.2017