Как работает токен продолжения Cosmos DB?
На первый взгляд ясно, что делает маркер продолжения в Cosmos DB: присоединение его к следующему запросу дает следующий набор результатов. Но что именно означает «следующий набор результатов»?
Значит ли это:
- следующий набор результатов, как если бы исходный запрос был выполнен полностью без разбиения на страницы во время самого первого запроса (пропуская соответствующее количество документов)?
- следующий набор результатов, как если бы исходный запрос был выполнен сейчас (пропуская соответствующее количество документов)?
- Что-то совсем другое?
Ответ 1. может показаться предпочтительным, но маловероятным, учитывая, что серверу необходимо хранить неограниченное количество состояний. Но ответ 2 также проблематичен, поскольку может привести к несогласованности, например, один и тот же документ может обслуживаться несколько раз на страницах, если базовые данные изменились между запросами страницы.
Ответы
Выполнение запросов Cosmos DB на стороне сервера не имеет состояния. Маркер продолжения используется для воссоздания состояния индекса и отслеживания хода выполнения.
«Следующий набор результатов» означает, что запрос выполняется снова из «закладки» из предыдущего выполнения. Эта закладка предоставляется токеном продолжения.
- Документы, созданные при продолжениях
Они могут возвращаться или не возвращаться в зависимости от позиции выполняемой вставки и запроса.
Пример:
ВЫБРАТЬ * ИЗ c ORDER BY c.someValue ASC
Предположим, что у закладки было someValue = 10, обработчик запросов возобновляет обработку, используя токен продолжения, где someValue = 10.
Если вы вставляете новый документ с someValue = 5 между выполнениями запроса, он не будет отображаться в следующем наборе результатов.
Если новый документ вставлен на «страницу», то есть на закладку, он появится в следующем наборе результатов.
- Документы обновляются во время продолжения
Та же логика, что и выше, применима и к обновлениям (см. №4)
- Документы удалены во время продолжения
Они не будут отображаться в следующем наборе результатов.
- Вероятность дублирования
В случае запроса ниже,
ВЫБРАТЬ * ИЗ c ORDER BY c.remainingInventory ASC
Если остаток инвентаря был обновлен после первого набора результатов и теперь удовлетворяет критериям ORDER BY для второй страницы, документ появится снова.
Cosmos DB не обеспечивает изоляцию снимков между страницами запросов. Однако, по мнению группы разработчиков, это невероятно необычный сценарий, потому что запросы по продолжению выполняются очень быстро, и в большинстве случаев все результаты запроса возвращаются на первой странице.
Исходя из предварительных экспериментов, ответ кажется вариантом №2, а точнее:
- Документы, созданные после обслуживания первой страницы, доступны для просмотра на последующих страницах.
- Документы, обновленные после обслуживания первой страницы, доступны для просмотра на последующих страницах.
- Документы, удаленные после обслуживания первой страницы, не отображаются на последующих страницах.
- Документы никогда не подаются дважды
Первое утверждение выше противоречит информации MSFT ( см . Ответ Каляна). Было бы здорово получить более квалифицированный ответ от команды Cosmos DB, точно определяющий семантику получения страниц. Это может быть не очень важно для отображения данных в пользовательском интерфейсе, но может иметь важное значение для обработки данных в бэкэнде, учитывая, что, похоже, нет никакого способа отключить разбиение на страницы при выполнении запроса ( см. Возможны ли транзакционные запросы в Cosmos DB? ).
Экспериментальный метод
Я использовал Cosmos DB Explorer Саши Бруттина для запроса коллекции с 5 документами, потому что этот инструмент позволяет поиграть с размером страницы и другими параметрами запроса.
Размер страницы был установлен на 1, и были включены межсекционные запросы. Были испробованы разные запросы, например, SELECT * FROM c
или SELECT * FROM c ORDER BY c.name
.
После получения страницы 1 были вставлены новые документы, а некоторые существующие документы (включая документы, которые должны были появиться на последующих страницах) были обновлены и удалены. Затем последовательно извлекались все последующие страницы.
(Быстрый просмотр исходного кода инструмента подтвердил, что ResponseContinuationTokenLimitInKb
он не установлен.)