MongoDb - повторяющиеся поля индекса для шардинга? - PullRequest
1 голос
/ 03 августа 2020

Я хочу построить кластер для хранения данных журналов. В каждом документе есть несколько полей, но это ключевые:

  • user_id (средняя мощность)
  • идентификатор (это имеет чрезвычайно высокую мощность, но не гарантируется, что она будет уникальной для пользователей, это может быть UP C например)
  • канал (низкая мощность)
  • временная метка

Ожидается, что в коллекции будет более 1 миллиарда документов, поэтому сегментирование и производительность здесь важны.

Теперь почти все высокочастотные запросы к коллекции будут иметь user_id, потому что журналы отображаются в пользовательском интерфейсе для каждого пользователя уникально. Большинство запросов будет на user_id + identifier. Некоторые запросы будут ограничены по времени. В некоторых запросах также используется channel, но не во всех. user_id - это монотонно увеличивающееся поле.

Я хочу разбить на hashed(user_id). Один идеальный индекс - {"user_id": 1, "identifier": 1, "timestamp": 1}, поэтому я его и сделал. Я пробовал шардинг на hashed(user_id), но в данном случае это не сработало, и я понял, что user_id должен быть того же типа. Однако создание индекса {"user_id": "hashed", "identifier": 1, "timestamp": 1} также невозможно, поскольку составные ключи с ha sh запрещены.

Какой мой лучший вариант здесь?

  • создать один индекс с просто hashed(user_id), чтобы я мог разделить его, а затем еще один индекс с {"user_id": 1, "identifier": 1, "timestamp": 1}? Я бы понес штраф за хранение здесь.
  • не иметь sh user_id, даже если он монотонно увеличивается, а вместо этого разбивается на {"user_id": 1, "identifier": 1}? Не уверен, есть ли здесь недостатки по сравнению с простым шардингом на hashed(user_id)
  • какой-то другой вариант?

Ответы [ 2 ]

1 голос
/ 03 августа 2020

создать один индекс с только что хешированным (user_id), чтобы я мог разделить его, а затем другой индекс с {"user_id": 1, "identifier": 1, "timestamp": 1}? Здесь я понесу штраф за хранение.

У вас может быть только один ключ осколка (и это должно быть индексированное, одиночное или составное поле). В случае поля хешированного индекса для ключа сегмента, начиная с MongoDB v4.2, это может быть только индекс одного поля.

Запрос сегментированной коллекции с критериями с использованием ключа сегмента (или префикса составного ключ шарда), будет целевым запросом. mongos получит доступ только к требуемому (-ым) осколку. Следовательно, это будет эффективный запрос.

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

См. Целевые операции и широковещательные операции .

не иметь sh user_id, даже если он монотонно увеличивается, а вместо этого разбивается на {"user_id": 1 , "идентификатор": 1}? Я не уверен, есть ли здесь недостатки по сравнению с простым шардингом по хешируемому (user_id)

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

MongoDB v4.4 (самая последняя версия) позволяет сегментирование хеширования по составному хешированному индексу .

1 голос
/ 03 августа 2020

Обратите внимание, что MongoDB 4.4 допускает составные индексы с одним хешированным полем: https://docs.mongodb.com/manual/core/hashed-sharding/

Если вы не можете легко выполнить обновление до 4.4, учитывая, что давление на хранилище здесь велико с большое количество документов и то, что большинство запросов будут содержать как user_id, так и identifier, сегментирование на {"user_id": 1, "identifier": 1} звучит как лучший вариант, который у вас есть. Это позволит выполнять эти запросы быстро за счет других ваших запросов, которые должны выполнять поиск по всем идентификаторам для каждого пользователя или по запросам на основе времени.

Я не уверен в лучшем решении для версии ниже MongoDB 4.4.

...