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