Melhores práticas para Coleções de séries temporais
Nesta página
- Práticas recomendadas de compressão
- Campos de omissão contendo objetos vazios e arrays de documentos
- Arredondar dados numéricos para poucos locais decimais
- Insere Melhores Práticas
- Gravações de documentos em lote
- Usar ordem de campo consistente em documentos
- Aumentar o número de clientes
- Práticas recomendadas de compartilhamento
- Use o
metaField
como sua chave de fragmento - Práticas recomendadas de query
- Defina um
metaField
estratégico ao criar a collection - Definir a granularidade apropriada do bucket
- Criar índices secundários
- Práticas recomendadas de índices adicionais
- Consulte o
metaField
em subcampos - Use $group em vez de Distinct()
Esta página descreve as melhores práticas para melhorar o desempenho e o uso de dados para coleções de séries temporais.
Práticas recomendadas de compressão
Para otimizar a compressão de dados para coleções de séries temporais, execute as seguintes ações:
Campos de omissão contendo objetos vazios e arrays de documentos
Se seus dados contiverem objetos, arrays ou strings vazios, omita os campos vazios dos documentos para otimizar a compressão.
Por exemplo, considere os seguintes documentos:
{ timestamp: ISODate("2020-01-23T00:00:00.441Z"), coordinates: [1.0, 2.0] }, { timestamp: ISODate("2020-01-23T00:00:10.441Z"), coordinates: [] }, { timestamp: ISODate("2020-01-23T00:00:20.441Z"), coordinates: [3.0, 5.0] }
coordinates
campos com valores preenchidos e campos coordinates
com uma array vazia resultam em uma alteração de esquema para o compressor. A mudança de esquema faz com que o segundo e o terceiro documentos da sequência permaneçam descompactados.
Otimize a compressão omitindo os campos com valores vazios, conforme mostrado nos seguintes documentos:
{ timestamp: ISODate("2020-01-23T00:00:00.441Z"), coordinates: [1.0, 2.0] }, { timestamp: ISODate("2020-01-23T00:00:10.441Z") }, { timestamp: ISODate("2020-01-23T00:00:20.441Z"), coordinates: [3.0, 5.0] }
Arredondar dados numéricos para poucos locais decimais
Arredonde os dados numéricos com a precisão que sua aplicação exige. Arredondar dados numéricos com menos casas decimais melhora a taxa de compressão.
Insere Melhores Práticas
Para otimizar o desempenho de inserção para coleções de séries temporais, execute as seguintes ações:
Gravações de documentos em lote
Ao inserir vários documentos:
Para evitar viagens de ida e volta de rede, use um único
insertMany()
em vez de vários comandosinsertOne()
.Se possível, insira dados que contenham valores de
metaField
idênticos nos mesmos lotes.Configure o parâmetro
ordered
parafalse
.
Por exemplo, se você tiver dois sensores que correspondem a dois valores metaField
, sensor A
e sensor B
, um lote que contém múltiplas medições de um único sensor incorrerá no custo de uma inserção, em vez de uma inserção por medida.
A operação a seguir insere seis documentos, mas só incorre no custo de duas inserções (uma por valor metaField
), pois os documentos são ordenados por sensor. O parâmetro ordered
é definido como false
para melhorar o desempenho:
db.temperatures.insertMany( [ { metaField: { sensor: "sensorA" }, timestamp: ISODate("2021-05-18T00:00:00.000Z"), temperature: 10 }, { metaField: { sensor: "sensorA" }, timestamp: ISODate("2021-05-19T00:00:00.000Z"), temperature: 12 }, { metaField: { sensor: "sensorA" }, timestamp: ISODate("2021-05-20T00:00:00.000Z"), temperature: 13 }, { metaField: { sensor: "sensorB" }, timestamp: ISODate("2021-05-18T00:00:00.000Z"), temperature: 20 }, { metaField: { sensor: "sensorB" }, timestamp: ISODate("2021-05-19T00:00:00.000Z"), temperature: 25 }, { metadField: { sensor: "sensorB" }, timestamp: ISODate("2021-05-20T00:00:00.000Z"), temperature: 26 } ], { "ordered": false } )
Usar ordem de campo consistente em documentos
Usar uma ordem de campo consistente em seus documentos melhora o desempenho da inserção.
Por exemplo, inserir os seguintes documentos, todos os quais têm a mesma ordem de campo , resulta em desempenho de inserção ideal.
{ _id: ObjectId("6250a0ef02a1877734a9df57"), timestamp: ISODate("2020-01-23T00:00:00.441Z"), name: "sensor1", range: 1 }, { _id: ObjectId("6560a0ef02a1877734a9df66"), timestamp: ISODate("2020-01-23T01:00:00.441Z"), name: "sensor1", range: 5 }
Por outro lado, os documentos a seguir não alcançam o desempenho ideal de inserção, porque suas ordens de campo diferem:
{ range: 1, _id: ObjectId("6250a0ef02a1877734a9df57"), name: "sensor1", timestamp: ISODate("2020-01-23T00:00:00.441Z") }, { _id: ObjectId("6560a0ef02a1877734a9df66"), name: "sensor1", timestamp: ISODate("2020-01-23T01:00:00.441Z"), range: 5 }
Aumentar o número de clientes
Aumentar o número de clientes que gravam dados em suas collections pode melhorar o desempenho.
Práticas recomendadas de compartilhamento
Para otimizar a fragmentação em sua coleção de séries temporais, execute a seguinte ação:
Use o metaField
como sua chave de fragmento
Usar metaField
para fragmentar sua collection fornece cardinalidade suficiente como uma chave de shard para coleções de séries temporais.
Observação
A partir do MongoDB 8.0, o uso do timeField
como uma chave de shard em coleções de séries temporais é preterido.
Práticas recomendadas de query
Para otimizar as queries em sua coleção de séries temporais, execute as seguintes ações:
Defina um estratégico metaField
ao criar a coleção
Sua escolha do metaField
tem o maior impacto na otimização de consultas em seu aplicação.
Selecione campos que raramente ou nunca mudam como parte do seu metaField.
Se possível, selecione identificadores ou outros valores estáveis que são comuns em expressões de filtro como parte do seu metaField.
Evite selecionar campos que não são usados para filtragem como parte do seu metaField. Em vez disso, use esses campos como medições.
Para obter mais informações, consulte Considerações sobre metaField.
Definir a granularidade apropriada do bucket
Quando você cria uma coleção de séries temporais, o MongoDB agrupa os dados de série temporal recebidos em buckets. Ao definir com precisão a granularidade, você controla a frequência com que os dados são colocados em buckets com base na taxa de ingestão de seus dados.
A partir do MongoDB 6.3, você pode usar os parâmetros de bucketing personalizados bucketMaxSpanSeconds
e bucketRoundingSeconds
para especificar os limites do bucket e controlar com mais precisão como os dados de série temporal são compartimentados.
Você pode melhorar o desempenho definindo os parâmetros de bucketing granularity
ou personalizados para a melhor correspondência referente ao intervalo de tempo entre as medições recebidas da mesma fonte de dados. Por exemplo, ao gravar dados meteorológicos com milhares de sensores, e apenas gravar dados de cada sensor uma vez a cada 5 minutos, você pode definir a granularity
em "minutes"
ou definir os parâmetros de bucketing personalizados para 300
(segundos).
Neste caso, definir a granularity
em hours
junta até um mês de eventos de ingestão de dados em um único bucket, resultando em tempos de travessia mais longos e queries mais lentas. Configurá-la como seconds
resulta em vários buckets por intervalo de sondagem, muitos dos quais podem conter somente um único documento.
A tabela abaixo mostra o intervalo de tempo máximo incluído em um bucket de dados ao utilizar um determinado valor granularity
:
granularity | granularity limite de bucket |
---|---|
seconds | 1 hora |
minutes | 24 horas |
hours | 30 dias |
Criar índices secundários
Para melhorar o desempenho da query, crie um ou mais índices secundários no seu timeField
e metaField
para suportar padrões de query comuns. Nas versões 6.3 e superior, o MongoDB cria automaticamente um índice secundário no timeField
e no metaField
.
Práticas recomendadas de índices adicionais
Use o índice metaField para filtragem e igualdade.
Use o timeField e outros campos indexados para queries de intervalo.
Estratégias gerais de indexação também se aplicam a coleções de séries temporais. Para obter mais informações, consulte Indexação de estratégias.
Consulte o metaField
em subcampos
O MongoDB reordena o metaField
das coleções de séries temporais, o que pode fazer com que os servidores armazenem dados em uma ordem de campo diferente da dos aplicativos. Se um metaField
for um objeto, as consultas no metaField
poderão produzir resultados inconsistentes porque a ordem do metaField
pode variar entre servidores e aplicativos. Para otimizar as queries em uma série temporal metaField
, consulte o metaField
em subcampos escalares em vez de todo o metaField
.
O exemplo a seguir cria uma coleção de séries temporais:
db.weather.insertMany( [ { metaField: { sensorId: 5578, type: "temperature" }, timestamp: ISODate( "2021-05-18T00:00:00.000Z" ), temp: 12 }, { metaField: { sensorId: 5578, type: "temperature" }, timestamp: ISODate( "2021-05-18T04:00:00.000Z" ), temp: 11 } ] )
A seguinte query nos subcampos escalares sensorId
e type
retorna o primeiro documento que corresponde aos critérios da query:
db.weather.findOne( { "metaField.sensorId": 5578, "metaField.type": "temperature" } )
Saída de exemplo:
{ _id: ObjectId("6572371964eb5ad43054d572"), metaField: { sensorId: 5578, type: 'temperature' }, timestamp: ISODate( "2021-05-18T00:00:00.000Z" ), temp: 12 }
Use $group em vez de Distinct()
Devido à estrutura de dados exclusiva das coleções de séries temporais, o MongoDB não pode indexá-las com eficiência para valores distintos. Evite usar o comando distinct
ou o método assistente db.collection.distinct()
em coleções de séries temporais. Em vez disso, use uma agregação $group
para agrupar documentos por valores distintos.
Por exemplo, para fazer query de valores meta.type
distintos em documentos onde meta.project = 10
, em vez de:
db.foo.distinct("meta.type", {"meta.project": 10})
Usar:
db.foo.createIndex({"meta.project":1, "meta.type":1}) db.foo.aggregate([{$match: {"meta.project": 10}}, {$group: {_id: "$meta.type"}}])
Isso funciona da seguinte forma:
Cria um índice composto em
meta.project
emeta.type
e oferece suporte à agregação.Os filtros de estágio
$match
para documentos ondemeta.project = 10
.O estágio
$group
usameta.type
como chave de grupo para gerar um documento por valor exclusivo.