Как сделать быстрые (er) агрегации на большом количестве записей в БД Cosmos? - PullRequest
0 голосов
/ 15 марта 2019

В настоящее время у меня есть документы, моделирующие электронные письма, которые немного похожи на следующие

{
    "AccountId": "AccountId",
    "Brand": "MyBrand",
    "Product": "MyProduct",
    "Metadata": {
        "Campaign": "EmailCampaign1",
        "Metadata2": "Some other info",
    },
    "Status": {
        "State": "delivered",
        "DeliveryEvents": [
            {
                "Event": "delivered",
                "DateTimeOccured": "2019-03-14T12:25:12Z",
            },
            {
                "Event": "processed",
                "DateTimeOccured": "2019-03-14T12:25:09Z"
            }
        ]
    },
    "id": "AnId",
    "CreatedAt": 1552566306,
    "Stats": {
        "DeliveryStats": {
            "processed": true,
            "deferred": false,
            "delivered": true,
            "dropped": false,
            "bounce": false
        }
    }
}

Для справки, AccountId в настоящее время является ключом разделения.

И я хотел сделатьCOUNT на DeliveryStats, где вы можете отфильтровать одно или несколько из следующих значений:

  • AccountId
  • Brand
  • Metadata(поиск пары ключ-значение)
  • CreatedAt (например, между двумя датами).

Вот пример запроса, который у меня есть в настоящее время для получения количества обработанных элементов с некоторымифильтры.В идеале я хотел бы получить счет всех различных DeliveryStats, но сейчас это кажется невозможным.

SELECT VALUE COUNT(1) FROM c WHERE c.Stats.DeliveryStats.processed = true AND c.Brand = 'MyBrand' AND c.Metadata.Campaign = 'EmailCampaign1'

Все запрашиваемые объекты индексируются.

Теперь это довольно быстро для небольших наборов данных, как и следовало ожидать, но как только вы начинаете зарабатывать миллионы, кажется, что загружается каждый документ (или я действительно читаю запросметрики неверны).

У меня вопрос, правильно ли написан этот запрос?Что еще я могу сделать, чтобы ускорить такой запрос?

Открыт для реструктуризации данных или хранения дополнительных данных.

1 Ответ

1 голос
/ 19 марта 2019

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

Индивидуальная селективность индекса

Достаточно ли избирательны ваши индексированные данные по отдельности ? Индексы CosmosDB хранят значения одного свойства, и, следовательно, даже если комбинация из 3 индексов может быть достаточно избирательной, CosmosDB, скорее всего, придется выбрать только один, чтобы быть основным индексом для сканирования. Если индексы индивидуально недостаточно избирательны, это может привести к снижению производительности, даже если комбинация была достаточно избирательной.

Если это так, вы можете объединить значения pf по отдельности с недостаточно избирательными значениями столбцов в одно свойство с хэш-индексированием для поиска. Пример:

{
    "AccountId": "AccountId",
    "Brand": "MyBrand",
    "Metadata": {
        "Campaign": "EmailCampaign1",
    },
    ...
    "MergedForLookup": "MyBrand_EmailCampaign_processed"
    ...
}

Очевидно, что поддержка N необязательных фильтров с любой возможной комбинацией того, что дано, является сложной задачей, но вы понимаете: обмен хранилищем на скорость .

Если вы не найдете хороших помощников по денормализации и абсолютно нуждаетесь в поиске по множеству комбинаций, то вам, возможно, придется включить внешний индекс для поиска . Например, посмотрите, как добавить Azure Search .

.

Перекрестный запрос

Следующий кандидат связан с тем, что вы делаете перекрестный запрос . В основном запрос по каждому разделу = N запросов. Если ваши данные растут до миллионов, то, скорее всего, у них много разделов (= accountIds) + ваши данные будут разделены на несколько физических разделов внутри, и это определенно окажет влияние. Если возможно, вы должны проверить, облегчит ли включение фильтра на AccountId. Если возможно, сделайте фильтр AccountId обязательным.

Является ли count () эффективным использованием индекса

Если запрос выполняется медленнее, чем вы ожидаете, даже с запросом с одним разделом, то были сообщения о том, что count() запросов не так эффективны, как можно ожидать . Проверьте следующую проблему и отдайте свои голоса: «Сделать COUNT () осведомленным об индексах» на CosmosDB Feedback .

.. количество всех разных DeliveryStats.

Да, AFAIK, который еще не поддерживается в одном запросе, но работает. Проверьте запрос «Добавить группу по поддержке агрегатных функций» .

Прямо сейчас, если фиксированных значений относительно немного, просто выполните эти 5 или любые другие запросы для каждого показателя подряд. Если каждый из них правильно использует раздел / индекс, он все равно должен быть молниеносным (в 5 раз молниеносным, если быть точным: P).

...