Запрашивает ли таблица Azure "ИЛИ" предикаты, вызывая сканирование?

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

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

или даже это:

(PartitionKey == 1 AND RowKey == A) ИЛИ (PartitionKey==2 AND 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 каждой сущности. Быстрее ли выполнить отдельный запрос для выборки каждой сущности параллельно или использовать предикат "ИЛИ" для пакетирования нескольких вызовов, чтобы минимизировать количество параллельных запросов?

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

Спасибо!

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

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

При выполнении теста я сделал:

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

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

(PK eq '0' и RK eq '0') или (PK eq '0' и RK eq '500') или... x400

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

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

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

PK eq '0' и (RK eq '0' или RK eq '500' или... x400)

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

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

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

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

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

1 ответ

Решение

PartitionKey==1 AND (RowKey==A ИЛИ RowKey==B) Результатом какого-либо из них является сканирование?

Да, это приведет к сканированию.

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

(PartitionKey == 1 AND RowKey == A) ИЛИ (PartitionKey==2 AND RowKey==B) Результатом какого-либо из этих действий является сканирование?

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам