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