Inúmeras coleções
Lauren Schaefer, Daniel Coupal6 min read • Published Feb 12, 2022 • Updated Oct 01, 2024
Avalie esse Artigo
Na primeira publicação desta série de antipadrões de projeto de esquema do MongoDB, analisamos como devemos evitar arrays gigantes ao projetar nossos esquemas. Mas e quem tem inúmeras coleções? Também não é uma boa ideia. Nesta publicação, vamos analisar o motivo.
Você prefere vídeos? Então aqui está.
Vamos começar discutindo por que ter inúmeras coleções é um antipadrão. Se o armazenamento é relativamente barato, por que ter muitas coleções seria um problema?
Cada coleção do MongoDB tem automaticamente um índice no campo _id. Embora o tamanho desse índice seja muito pequeno para coleções vazias ou pequenas, milhares de índices vazios ou não utilizados podem começar a drenar recursos. As coleções normalmente terão mais alguns índices para permitir queries eficientes. Todos esses índices acabam se acumulando.
Em geral, recomendamos limitar as coleções a 10.000 por conjunto de réplicas. Quando os usuários começam a exceder as 10.000 coleções, geralmente observam quedas no desempenho.
Para evitar esse antipadrão, examine seu banco de dados e remova coleções desnecessárias. Se você achar que tem um número cada vez maior de coleções, considere remodelar seus dados para ter um conjunto consistente de coleções.
Eu vou usar de exemplo um programa de TV dos EUA que eu adoro: Parks and Recreation (Confusões de Leslie, no Brasil). A Leslie ama cuidar dos parques que supervisiona, e chega uma hora em que ela resolve que é responsabilidade dela remover o lixo do rio Pawnee.
Digamos que ela queira manter um registro minuto a minuto do nível e da temperatura da água do rio Pawnee, do rio Eagleton e do rio Wamapoke, para poder procurar tendências. Ela poderia enviar a seu colega de trabalho Gerry para colocar 30 sensores em cada rio e, em seguida, começar a armazenar os dados do sensor em um MongoDB database.
Uma maneira de armazenar os dados seria criar uma nova coleção todos os dias para armazenar dados do sensor. Cada coleção conteria documentos que armazenariam informações sobre 1 (uma) leitura de 1 (um) sensor.
1 // 2020-05-01 collection 2 { 3 "_id": ObjectId("5eac643e64faf3ff31d70d35"), 4 "river": "PawneeRiver", 5 "sensor": 1 6 "timestamp": "2020-05-01T00:00:00Z", 7 "water-level": 61.56, 8 "water-temperature": 72.1 9 }, 10 { 11 "_id": ObjectId("5eac643e64faf3ff31d70d36"), 12 "river": "PawneeRiver", 13 "sensor": 2 14 "timestamp": "2020-05-01T00:00:00Z", 15 "water-level": 61.55, 16 "water-temperature": 72.1 17 }, 18 ... 19 { 20 "_id": ObjectId("5eac643e64faf3ff31d70dfc"), 21 "river": "WamapokeRiver", 22 "sensor": 90 23 "timestamp": "2020-05-01T23:59:00Z", 24 "water-level": 72.03, 25 "water-temperature": 64.1 26 } 27 28 // 2020-05-02 collection 29 { 30 "_id": ObjectId("5eac644c64faf3ff31d90775"), 31 "river": "PawneeRiver", 32 "sensor": 1 33 "timestamp": "2020-05-02T00:00:00Z", 34 "water-level": 63.12, 35 "water-temperature": 72.8 36 }, 37 { 38 "_id": ObjectId("5eac644c64faf3ff31d90776"), 39 "river": "PawneeRiver", 40 "sensor": 2 41 "timestamp": "2020-05-02T00:00:00Z", 42 "water-level": 63.11, 43 "water-temperature": 72.7 44 }, 45 ... 46 { 47 "_id": ObjectId("5eac644c64faf3ff31d9079c"), 48 "river": "WamapokeRiver", 49 "sensor": 90 50 "timestamp": "2020-05-02T23:59:00Z", 51 "water-level": 71.58, 52 "water-temperature": 66.2 53 }
Digamos que a Leslie queira executar queries facilmente nos campos
river
e sensor
, então ela cria um índice em cada campo.Se a Leslie fosse armazenar dados por hora em todos os 2019 e criasse dois índices em cada coleção (além do índice padrão em
_id
), seu banco de dados teria as seguintes estatísticas:- Tamanho do banco de dados: 5.2 GB
- Tamanho do índice: 1,07 GB
- Total de Coleções: 365
Isso para cada dia que ela criasse uma nova coleção e dois índices. Como a Leslie continua a coletar dados e seu número de coleções ultrapassa 10.000, o desempenho do seu banco de dados diminuirá.
Além disso, quando Leslie quiser procurar tendências ao longo de semanas e meses, ela terá dificuldade em fazê-lo, já que seus dados estão espalhados por várias coleções.
Digamos que a Leslie perceba que este não é um ótimo esquema e ela resolva reestruturar seus dados. Desta vez, ela decide manter todos os seus dados em uma única coleção. Ela agrupará suas informações para armazenar uma hora de informações de um sensor em cada documento.
1 // data collection 2 { 3 "_id": "PawneeRiver-1-2019-05-01T00:00:00.000Z", 4 "river": "PawneeRiver", 5 "sensor": 1, 6 "readings": [ 7 { 8 "timestamp": "2019-05-01T00:00:00.000+00:00", 9 "water-level": 61.56, 10 "water-temperature": 72.1 11 }, 12 { 13 "timestamp": "2019-05-01T00:01:00.000+00:00", 14 "water-level": 61.56, 15 "water-temperature": 72.1 16 }, 17 ... 18 { 19 "timestamp": "2019-05-01T00:59:00.000+00:00", 20 "water-level": 61.55, 21 "water-temperature": 72.0 22 } 23 ] 24 }, 25 ... 26 { 27 "_id": "PawneeRiver-1-2019-05-02T00:00:00.000Z", 28 "river": "PawneeRiver", 29 "sensor": 1, 30 "readings": [ 31 { 32 "timestamp": "2019-05-02T00:00:00.000+00:00", 33 "water-level": 63.12, 34 "water-temperature": 72.8 35 }, 36 { 37 "timestamp": "2019-05-02T00:01:00.000+00:00", 38 "water-level": 63.11, 39 "water-temperature": 72.8 40 }, 41 ... 42 { 43 "timestamp": "2019-05-02T00:59:00.000+00:00", 44 "water-level": 63.10, 45 "water-temperature": 72.7 46 } 47 ] 48 } 49 ...
A Leslie quer executar queries nos campos
river
sensor
, então ela cria dois novos índices para essa coleção.Se a Leslie fosse armazenar dados por hora para todos os 2019 usando esse esquema atualizado, seu banco de dados teria as seguintes estatísticas:
- Tamanho do banco de dados: 3.07 GB
- Tamanho do índice: 27.45 MB
- Total de Coleções: 1
Ao reestruturar seus dados, ela vê uma grande redução no tamanho do índice (1.07 GB inicialmente para 27.45 MB!). Ela agora tem uma única coleção com três índices.
Com esse novo esquema, ela pode procurar tendências em seus dados com mais facilidade, pois eles são armazenados em uma única coleção. Além disso, ela está usando o índice padrão em
_id
a seu favor, armazenando a hora em que os dados de nível de água foram coletados neste campo. Se ela quiser consultar por hora, ela já tem um índice que lhe permite fazê-lo de forma eficiente.Para obter mais informações sobre modelagem de dados de série temporal no MongoDB, consulte Criar com padrões: o padrão de bucket.
No exemplo acima, a Leslie conseguiu remover coleções desnecessárias alterando a forma como armazenava seus dados.
Às vezes, você não saberá imediatamente quais coleções são desnecessárias, portanto, terá de investigar por conta própria. Se encontrar uma coleção vazia, poderá descartar. Se encontrar uma coleção cujo tamanho é composto principalmente de índices, provavelmente poderá mover esses dados para outra coleção e descartar a original. Você pode usar $merge para mover dados de uma coleção para outra.
Abaixo estão algumas maneiras pelas quais você pode começar sua investigação.
Se o seu banco de dados estiver hospedado no Atlas, navegue até o Atlas Data Explorer. O Data Explorer permite que você navegue por uma lista de seus bancos de dados e coleções. Além disso, você pode obter estatísticas sobre seu banco de dados, incluindo o tamanho do banco de dados, o tamanho do índice e o número de coleções.
Se você estiver usando um cluster M10 ou maior no Atlas, também poderá usar o Real-Time Performance Panel para verificar se a aplicação está usando ativamente uma coleção que você está pensando em descartar.
Independentemente do local onde seu MongoDB database esteja hospedado, você pode usar o MongoDB Compass, que é a interface de usuário do MongoDB para desktop. Assim como o Data Explorer, você pode navegar nos seus bancos de dados e coleções para verificar se há coleções não utilizadas. Você também pode obter estatísticas nos níveis do banco de dados e da coleção.
Se você preferir usar um terminal em vez de em uma interface gráfica, conecte-se ao seu banco de dados usando o Mongo Shell.
Para ver uma lista de coleções, execute
db.getCollectionNames()
. Serão exibidas saídas como esta:1 [ 2 "2019-01-01", 3 "2019-01-02", 4 "2019-01-03", 5 "2019-01-04", 6 "2019-01-05", 7 ... 8 ]
Para recuperar estatísticas sobre seu banco de dados, execute
db.stats()
. Uma saída como a seguinte será exibida:1 { 2 "db" : "riverstats", 3 "collections" : 365, 4 "views" : 0, 5 "objects" : 47304000, 6 "avgObjSize" : 118, 7 "dataSize" : 5581872000, 8 "storageSize" : 1249677312, 9 "numExtents" : 0, 10 "indexes" : 1095, 11 "indexSize" : 1145790464, 12 "scaleFactor" : 1, 13 "fsUsedSize" : 5312217088, 14 "fsTotalSize" : 10726932480, 15 "ok" : 1, 16 "$clusterTime" : { 17 "clusterTime" : Timestamp(1588795184, 3), 18 "signature" : { 19 "hash" : BinData(0,"orka3bVeAiwlIGdbVoP+Fj6N01s="), 20 "keyId" : NumberLong("6821929184550453250") 21 } 22 }, 23 "operationTime" : Timestamp(1588795184, 3) 24 }
Você também pode executar
db.collection.stats()
para ver informações sobre uma coleção específica.Tenha cuidado ao criar uma quantidade muito grande coleções, porque cada coleção provavelmente ainda terá alguns índices. Um número excessivo de coleções e seus respectivos índices podem drenar recursos e afetar o desempenho do banco de dados. Em geral, tente limitar seu conjunto de réplicas a 10.000 coleções.
Volte em breve para a próxima postagem desta série de antipadrões!
Quando quiser criar um esquema no MongoDB, confira o MongoDB Atlas, que é o banco de dados como serviço totalmente gerenciado do MongoDB. O Atlas é a maneira mais fácil de começar a usar o MongoDB. Com um nível grátis permanente, você está no caminho certo para aproveitar todo o valor do MongoDB.
Confira os seguintes recursos para obter mais informações: