Melhores práticas para Coleções de séries temporais
Nesta página
- Melhores práticas de compactaçã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
- Melhores práticas de fragmentação
- Use o
metaField
como sua chave de fragmento - Práticas recomendadas de query
- Defina um
metaField
estratégico ao criar a coleção - Definir a granularidade apropriada do bucket
- Criar índices secundários
- Práticas recomendadas adicionais de índice
- Fazer query nos subcampos
metaField
- 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.
Melhores práticas de compactação
Para otimizar a compactaçã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 compactaçã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 compactação omitindo os campos com valores em branco, 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 seu aplicativo exige. O arredondamento dos dados numéricos para menos casas decimais melhora a taxa de compactaçã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 idas e vindas da rede, use um único comando
insertMany()
em vez de vários comandosinsertOne()
.Se possível, insira dados que contenham valores
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 várias medições de um único sensor incorre no custo de um inserto, em vez de um inserto por medição.
A operação a seguir insere seis documentos, mas incorre apenas no custo de duas inserções (uma por cada valor metaField
), pois os documentos são ordenados por sensor. O parâmetro ordered
está configurado para 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, a inserção dos seguintes documentos, todos com a mesma ordem de campos, resulta em um 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 atingem o desempenho ideal de inserção, pois suas ordens de campo são diferentes:
{ 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 coleções pode melhorar o desempenho.
Melhores práticas de fragmentação
Para otimizar a fragmentação na sua coleção de séries temporais, execute a seguinte ação:
Use o metaField
como sua chave de fragmento
Usar o metaField
para fragmentar sua coleção fornece cardinalidade suficiente como uma chave de fragmentação para coleções de séries temporais.
Observação
A partir do MongoDB 8.0, o uso de timeField
como uma chave de fragmento em coleções de séries temporais será descontinuado.
Práticas recomendadas de query
Para otimizar as consultas em sua coleção de séries temporais, execute as seguintes ações:
Defina um metaField
estratégico ao criar a coleção
Sua escolha de metaField
tem o maior impacto na otimização de consultas em seu aplicativo.
Selecione campos que raramente ou nunca mudam como parte do seu MetaField.
Se possível, selecione identificadores ou outros valores estáveis que sejam comuns em expressões de filtro como parte de seu metaField.
Evite selecionar campos que não sejam usados para filtragem como parte do seu MetaField. Em vez disso, use esses campos como medidas.
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 adicionais de índice
Use o índice metaField para filtragem e igualdade.
Use o timeField e outros campos indexados para consultas de intervalo.
As estratégias gerais de indexação também se aplicam às coleções de séries temporais. Para obter mais informações, consulte Estratégias de indexação.
Execute uma query no metaField
nos subcampos
O MongoDB reordena os metaField
de coleções de séries temporais, o que pode fazer com que os servidores armazenem dados em uma ordem de campo diferente dos aplicativos. Se um metaField
for um objeto, as queries no metaField
podem produzir resultados inconsistentes porque a ordem metaField
pode variar entre servidores e aplicativos. Para otimizar queries em uma série temporal metaField
, faça query em subcampos escalares metaField
em vez de em 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 única das coleções de séries temporais, o MongoDB não pode indexá-las de forma eficiente para valores diferentes. Evite usar o comando distinct
ou 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 consultar valores meta.type
diferentes 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 maneira:
Criando um índice composto em
meta.project
emeta.type
e é compatível com a agregação.O estágio
$match
filtra documentos ondemeta.project = 10
.O estágio
$group
usameta.type
como a chave de grupo para gerar um documento por valor exclusivo.