Временные ряды MongoDB для историка процессов: запрос по разным байтам поля _id

Я хочу хранить данные таймсерий в mongodb. Я знаю, знаю, в сети есть много статей об этом, но ни одна не предлагала решение именно моей проблемы, и многие из них относятся к старому механизму хранения mmap, и я использую WiredTiger, и многие из них иметь дело с равноудаленными таймсериями. Цель состоит в том, чтобы достичь наилучшего компромисса между пропускной способностью чтения и записи, обеспечивая при этом максимальную масштабируемость (даже до терабайт данных временных рядов) и минимальный размер дискового хранилища / потребление оперативной памяти. Это также означает минимальное количество индексов. У историка должна быть возможность импортировать прошлые данные, поэтому новые данные не всегда добавляются с увеличивающейся временной меткой. Я уже разработал минималистичную схему:

{
    "_id": "f061e95ae4dc281aea4df2f8",
    "Values": [
        {
            "Time": "2018-05-02T07:56:40.545Z",
            "Value": "529"
        },
        {
            "Time": "2018-05-02T07:56:51.119Z",
            "Value": "254"
        },
...
    ]
}

Этот документ представляет один фрагмент данных, который принадлежит одному сигналу, и один один час по времени (данные будут иметь наименьшее, но неэквидистантное время выборки, составляющее около 1 секунды). Коллекция содержит только такие документы и имеет только один индекс (конечно, по _id). _Id документа генерируется на основе хэша уникального идентификатора этого сигнала и начала часа utc, которому принадлежит сегмент данных.

Как видите, для запроса данных я вычисляю набор идентификаторов на основе заданного временного диапазона и идентификатора сигнала. Первые 4 байта _id кодируют час utc, последние 8 байтов - хэш идентификатора сигнала. Следовательно, запрос, запрашивающий данные за один день для одного сигнала, приведет к запросу, пытающемуся получить 24 идентификатора. Проблема в том, что для больших временных диапазонов (например, начиная с эпохи до настоящего времени) мне приходится запрашивать множество идентификаторов (например, 400000), что, похоже, делает запрос довольно медленным. (Сокращенный) запрос mongodb db (на C#):

FilterDefinition<DBTimeSeries> f = Builders<DBTimeSeries>.Filter.Empty;
var filterbuilder = Builders<DBTimeSeries>.Filter;
IEnumerable ids = Helpers.GetIDs(start, end, tagname);
var f = Builders<DBTimeSeries>.Filter.Empty;
f = f & filterbuilder.In(x => x.ID, ids);
var chunks = await collection.FindAsync<DBTimeSeries>(f);

Даже при небольшом количестве данных в базе данных выполнение этого запроса занимает до одной минуты. Свойство ID имеет тип ObjectId из драйвера mongodb C#.

Я знаю что это возможно

f = f & filterbuilder.Where(x => x.ID > new ObjectId(DateTime.Now.AddDays(-1), 0, 0, 0) && x.ID < new ObjectId(DateTime.Now, 0, 0, 0))

Это означает, что я могу выполнять запросы временного диапазона по идентификаторам, но это не дает мне возможности запрашивать данные для одного конкретного сигнала без добавления дополнительного поля в документ, представленный выше. Мне даже пришлось бы проиндексировать это поле для лучшей производительности.

Поэтому мой вопрос: было бы оптимальным иметь возможность запрашивать _id с помощью такого запроса: «Дайте мне документы, первые 4 байта поля _id которых представляют uint32 между x и y, а последние 8 байтов поля _id - равный заданному unit64 ". Запрос должен использовать исключительно индексы, что должно быть возможно, поскольку вся информация хранится в поле _id. Я знаю о параметре $ bitsAllSet (https://docs.mongodb.com/manual/reference/operator/query/bitsAllSet/#op._S_bitsAllSet), но я могу каким-то образом передать только long в драйвере C#, и запросы, похоже, не могут использовать индекс для части запроса $ bitsAllSet ...

У кого-нибудь есть идея? Спасибо всем заранее.

Можно ли будет реструктурировать ваши данные? Использование поля _id для хранения идентификатора сигнала и метки времени корзины затрудняет их индексацию. Не могли бы вы сохранить идентификатор сигнала как одно поле, а временную метку корзины как отдельное поле даты, что позволит вам индексировать их как обычно?

Vince Bowdren 02.05.2018 15:41

Спасибо за помощь, Винс! Да, конечно, добавление поля индексированного идентификатора сигнала в документ корзины было бы простым решением, но теоретически все, что мне нужно, доступно в поле _id таким образом. Было бы здорово, если бы проблема могла быть решена с использованием только одного индекса, если бы я мог даже сделать запрос временного диапазона по _id (который в конечном итоге является запросом по первым 4 байтам _id), это также должно быть возможно включить в запрос гораздо менее сложный оператор «сопоставить последние 8 байтов _id с шаблоном, который я вам предоставляю».

heapoverflow 02.05.2018 16:08

ОК, имеет смысл. Я взял на себя смелость отредактировать заголовок вашего вопроса, чтобы попытаться зафиксировать важную часть того, что вы пытаетесь сделать. Помните, вам рекомендуется редактировать и при необходимости повторно редактировать вопросы, чтобы улучшить их в максимально возможной степени.

Vince Bowdren 02.05.2018 16:14

@heapoverflow несколько вопросов 1) Не могли бы вы опубликовать вывод объяснять()? 2) почему у вас значение _id в строковом формате? 3) Будет ли ваше значение _id последовательным? Я бы так предположил, но просто чтобы подтвердить. Спасибо.

Wan Bachtiar 31.07.2018 06:11
Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
1
4
168
0

Другие вопросы по теме