SlideShare a Scribd company logo
MongoDB: Schema
 Design at Scale


     Rick Copeland
       @rick446
    http://arborian.com
Who am I?

• Now a consultant/trainer, but formerly...
 • Software engineer at SourceForge
 • Author of Essential SQLAlchemy
 • Author of MongoDB with Python and Ming
 • Primarily code Python
The Inspiration
• MongoDB monitoring service
  (MMS)
• Free to all MongoDB users
• Minute-by-minute stats on all
  your servers
• Hardware cost is important,
  use it efficiently (remember it’s
  a free service!)
Our Experiment
• Similar to MMS but not identical
• Collection of 100 metrics, each with per-
  minute values
• “Simulation time” is 300x real time
• Run on 2x AWS small instance
 • one MongoDB server (2.0.2)
 • one “load generator”
Load Generator

• Increment each metric as many times as
  possible during the course of a simulated
  minute
• Record number of updates per second
• Occasionally call getLastError to prevent
  disconnects
Schema v1
{
    _id: "20101010/metric-1",
    metadata: {
        date: ISODate("2000-10-10T00:00:00Z"),
        metric: "metric-1" },                    •   One document
    daily: 5468426,
    hourly: {
                                                     per metric (per
        "00": 227850,                                server) per day
        "01": 210231,
        ...
        "23": 20457 },
    minute: {                                    •   Per hour/minute
        "0000": 3612,                                statistics stored as
        "0001": 3241,
        ...                                          documents
        "1439": 2819 }
}
Update v1
                                     •   Use $inc to
                                         update fields in-
                                         place
increment = { daily: 1 }
increment['hourly.' + hour] = 1
increment['minute.' + minute] = 1
                                     •   Use upsert to
db.stats.update(
  { _id: id, metadata: metadata },
                                         create document
  { $inc: update },                      if it’s missing
  true) // upsert


                                     •   Easy, correct,
                                         seems like a good
                                         idea....
Performance of v1
Performance of v1

              Experiment startup
Performance of v1

                Experiment startup




            OUCH!
Problems with v1

• The document movement problem
• The midnight problem
• The end-of-the-day problem
• The historical query problem
Document movement
     problem
• MongoDB in-place updates are fast
 • ... except when they’re not in place
• MongoDB adaptively pads documents
 • ... but it’s better to know your doc size
    ahead of time
Midnight problem

• Upserts are convenient, but what’s our key?
 • date/metric
• At midnight, you get a huge spike in inserts
Fixing the document
          movement problem
                                     •   Preallocate
db.stats.update(
                                         documents with
  { _id: id, metadata: metadata },       zeros
  { $inc: {
    daily: 0,
    hourly.0: 0,
    hourly.1: 0,
    ...
                                     •   Crontab (?)
    minute.0: 0,
    minute.1: 0,
    ... }                                • NO! (makes
  true) // upsert                          the midnight
                                           problem even
                                           worse)
Fixing the midnight
      problem
Fixing the midnight
         problem
• Could schedule preallocation for different
  metrics, staggered through the day
Fixing the midnight
         problem
• Could schedule preallocation for different
  metrics, staggered through the day
• Observation: Preallocation isn’t required for
  correct operation
Fixing the midnight
         problem
• Could schedule preallocation for different
  metrics, staggered through the day
• Observation: Preallocation isn’t required for
  correct operation
• Let’s just preallocate tomorrow’s docs
  randomly as new stats are inserted (with
  low probability).
Performance with
  Preallocation


     Experiment startup
Performance with
  Preallocation

                          • Well, it’s better
     Experiment startup
Performance with
  Preallocation

                          • Well, it’s better
                          • Still have
     Experiment startup     decreasing
                            performance
                            through the day...
                            WTF?
Performance with
  Preallocation

                          • Well, it’s better
                          • Still have
     Experiment startup     decreasing
                            performance
                            through the day...
                            WTF?
Problems with v1

• The document movement problem
• The midnight problem
• The end-of-the-day problem
• The historical query problem
End-of-day problem
“0000” Value “0001” Value           “1439” Value




•   Bson stores documents as an association list

•   MongoDB must check each key for a match

•   Load increases significantly at the end of the day
    (MongoDB must scan 1439 keys to find the right minute!)
Fixing the end-of-day
                problem
                                             •
{ _id: "20101010/metric-1",
  metadata: {                                    Split up our
    date: ISODate("2000-10-10T00:00:00Z"),
    metric: "metric-1" },                        ‘minute’ property
  daily: 5468426,
  hourly: {                                      by hour
    "0": 227850,
    "1": 210231,
    ...
    "23": 20457 },                           •   Better worst-case
  minute: {                                      keys scanned:
    "00": {
        "0000": 3612,
        "0100": 3241,
        ...
    }, ...,
                                                 •   Old: 1439
    "23": { ..., "1439": 2819 }
}
                                                 •   New: 82
“Hierarchical minutes”
    Performance
Performance
Comparision
Performance
Comparision (2.2)
Historical Query
         Problem

• Intra-day queries are great
• What about “performance year to date”?
 • Now you’re hitting a lot of “cold”
    documents and causing page faults
Fixing the historical
              query problem
                                             •   Store multiple levels
{ _id: "201010/metric-1",                        of granularity in
  metadata: {
    date: ISODate("2000-10-01T00:00:00Z"),       different collections
    metric: "metric-1" },

                                             •
  daily: {
    "0": 5468426,                                2 updates rather than
    "1": ...,
    ...                                          1, but historical
}
    "31": ... },
                                                 queries much faster

                                             •   Preallocate along with
                                                 daily docs (only
                                                 infrequently upserted)
Queries
db.stats.daily.find( {                           •   Updates are by
    "metadata.date": { $gte: dt1, $lte: dt2 },
    "metadata.metric": "metric-1"},
                                                     _id, so no index
{ "metadata.date": 1, "hourly": 1 } },               needed there
sort=[("metadata.date", 1)])


                                                 •   Chart queries are
                                                     by metadata

db.stats.daily.ensureIndex({
  'metadata.metric': 1,
                                                 •   Your range/sort
  'metadata.date': 1 })                              should be last in
                                                     the compound
                                                     index
Conclusion
• Monitor your performance. Watch out for
  spikes.
• Preallocate to prevent document copying
• Pay attention to the number of keys in your
  documents (hierarchy can help)
• Make sure your index is optimized for your
  sorts
Questions?
          MongoDB Monitoring Service
http://www.10gen.com/mongodb-monitoring-service




                Rick Copeland
                   @rick446
              http://arborian.com
         MongoDB Consulting & Training

More Related Content

What's hot (10)

PDF
MySQL Performance Monitoring
spil-engineering
 
PDF
Retaining globally distributed high availability
spil-engineering
 
PDF
Storing metrics at scale with Gnocchi
Gordon Chung
 
PDF
Disco workshop
spil-engineering
 
PDF
A Hitchhiker's Guide to NOSQL v1.0
Krishna Sankar
 
PDF
MongoDB World 2018: Overnight to 60 Seconds: An IOT ETL Performance Case Study
MongoDB
 
PDF
Database TCO
spil-engineering
 
PDF
Performance Schema in MySQL (Danil Zburivsky)
Ontico
 
PDF
Cassandra Day Atlanta 2015: Diagnosing Problems in Production
DataStax Academy
 
PDF
Webinar: Diagnosing Apache Cassandra Problems in Production
DataStax Academy
 
MySQL Performance Monitoring
spil-engineering
 
Retaining globally distributed high availability
spil-engineering
 
Storing metrics at scale with Gnocchi
Gordon Chung
 
Disco workshop
spil-engineering
 
A Hitchhiker's Guide to NOSQL v1.0
Krishna Sankar
 
MongoDB World 2018: Overnight to 60 Seconds: An IOT ETL Performance Case Study
MongoDB
 
Database TCO
spil-engineering
 
Performance Schema in MySQL (Danil Zburivsky)
Ontico
 
Cassandra Day Atlanta 2015: Diagnosing Problems in Production
DataStax Academy
 
Webinar: Diagnosing Apache Cassandra Problems in Production
DataStax Academy
 

Viewers also liked (17)

PDF
MongoDB Schema Design (Richard Kreuter's Mongo Berlin preso)
MongoDB
 
PPT
MongoDB Schema Design
MongoDB
 
PPTX
MongoDB Schema Design: Four Real-World Examples
Mike Friedman
 
PDF
Using communication and messaging API in the HTML5 world - GIl Fink, sparXsys
Codemotion Tel Aviv
 
PDF
MongoDB Schema Design
aaronheckmann
 
PPTX
MongoDB Schema Design by Examples
Hadi Ariawan
 
PDF
10gen MongoDB Video Presentation at WebGeek DevCup
WebGeek Philippines
 
PPTX
How Insurance Companies Use MongoDB
MongoDB
 
PPT
Real World MongoDB: Use Cases from Financial Services by Daniel Roberts
MongoDB
 
PPT
How Retail Banks Use MongoDB
MongoDB
 
PDF
How Financial Services Organizations Use MongoDB
MongoDB
 
PPTX
Scalable Event Analytics with MongoDB & Ruby on Rails
Jared Rosoff
 
KEY
Schema Design with MongoDB
rogerbodamer
 
PPTX
MongoDB Advanced Schema Design - Inboxes
Jared Rosoff
 
KEY
Modeling Data in MongoDB
lehresman
 
PPTX
MongoDB for Time Series Data: Setting the Stage for Sensor Management
MongoDB
 
PPTX
MongoDB for Time Series Data: Schema Design
MongoDB
 
MongoDB Schema Design (Richard Kreuter's Mongo Berlin preso)
MongoDB
 
MongoDB Schema Design
MongoDB
 
MongoDB Schema Design: Four Real-World Examples
Mike Friedman
 
Using communication and messaging API in the HTML5 world - GIl Fink, sparXsys
Codemotion Tel Aviv
 
MongoDB Schema Design
aaronheckmann
 
MongoDB Schema Design by Examples
Hadi Ariawan
 
10gen MongoDB Video Presentation at WebGeek DevCup
WebGeek Philippines
 
How Insurance Companies Use MongoDB
MongoDB
 
Real World MongoDB: Use Cases from Financial Services by Daniel Roberts
MongoDB
 
How Retail Banks Use MongoDB
MongoDB
 
How Financial Services Organizations Use MongoDB
MongoDB
 
Scalable Event Analytics with MongoDB & Ruby on Rails
Jared Rosoff
 
Schema Design with MongoDB
rogerbodamer
 
MongoDB Advanced Schema Design - Inboxes
Jared Rosoff
 
Modeling Data in MongoDB
lehresman
 
MongoDB for Time Series Data: Setting the Stage for Sensor Management
MongoDB
 
MongoDB for Time Series Data: Schema Design
MongoDB
 
Ad

Similar to Schema Design at Scale (20)

PDF
MongoDB Performance Tuning
MongoDB
 
PPTX
Operational Intelligence with MongoDB Webinar
MongoDB
 
PPTX
Deployment Preparedness
MongoDB
 
PDF
Lab pratico per la progettazione di soluzioni MongoDB in ambito Internet of T...
festival ICT 2016
 
PDF
MongoDB Solution for Internet of Things and Big Data
Stefano Dindo
 
KEY
An Evening with MongoDB - Orlando: Welcome and Keynote
MongoDB
 
PPTX
MongoDB Use Cases: Healthcare, CMS, Analytics
MongoDB
 
PDF
MongoDB for Analytics
MongoDB
 
KEY
Mongo scaling
Simon Maynard
 
PDF
Optimizing Slow Queries with Indexes and Creativity
MongoDB
 
PPTX
High Performance Applications with MongoDB
MongoDB
 
PDF
Latinoware
kchodorow
 
PPTX
Scaling with MongoDB
Rick Copeland
 
PDF
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
MongoDB
 
PPTX
MongoDb Schema Pattern - Kalpit Pandit.pptx
KalpitPandit1
 
PDF
Harmony intune final
MongoDB
 
PDF
Playing in Tune: How We Refactored Cube to Terabyte Scale
MongoDB
 
PDF
MongoDB: Optimising for Performance, Scale & Analytics
Server Density
 
PDF
MongoDB in FS
MongoDB
 
PPTX
Dev Jumpstart: Build Your First App with MongoDB
MongoDB
 
MongoDB Performance Tuning
MongoDB
 
Operational Intelligence with MongoDB Webinar
MongoDB
 
Deployment Preparedness
MongoDB
 
Lab pratico per la progettazione di soluzioni MongoDB in ambito Internet of T...
festival ICT 2016
 
MongoDB Solution for Internet of Things and Big Data
Stefano Dindo
 
An Evening with MongoDB - Orlando: Welcome and Keynote
MongoDB
 
MongoDB Use Cases: Healthcare, CMS, Analytics
MongoDB
 
MongoDB for Analytics
MongoDB
 
Mongo scaling
Simon Maynard
 
Optimizing Slow Queries with Indexes and Creativity
MongoDB
 
High Performance Applications with MongoDB
MongoDB
 
Latinoware
kchodorow
 
Scaling with MongoDB
Rick Copeland
 
Ensuring High Availability for Real-time Analytics featuring Boxed Ice / Serv...
MongoDB
 
MongoDb Schema Pattern - Kalpit Pandit.pptx
KalpitPandit1
 
Harmony intune final
MongoDB
 
Playing in Tune: How We Refactored Cube to Terabyte Scale
MongoDB
 
MongoDB: Optimising for Performance, Scale & Analytics
Server Density
 
MongoDB in FS
MongoDB
 
Dev Jumpstart: Build Your First App with MongoDB
MongoDB
 
Ad

More from Rick Copeland (11)

PDF
Python Functions (PyAtl Beginners Night)
Rick Copeland
 
KEY
Building Your First MongoDB Application
Rick Copeland
 
PPTX
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rick Copeland
 
PPTX
Chef on MongoDB and Pyramid
Rick Copeland
 
PDF
Chef on Python and MongoDB
Rick Copeland
 
PPT
Real-Time Python Web: Gevent and Socket.io
Rick Copeland
 
PPT
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rick Copeland
 
PPT
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
Rick Copeland
 
PPT
Rapid, Scalable Web Development with MongoDB, Ming, and Python
Rick Copeland
 
PPT
Allura - an Open Source MongoDB Based Document Oriented SourceForge
Rick Copeland
 
PPT
MongoATL: How Sourceforge is Using MongoDB
Rick Copeland
 
Python Functions (PyAtl Beginners Night)
Rick Copeland
 
Building Your First MongoDB Application
Rick Copeland
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rick Copeland
 
Chef on MongoDB and Pyramid
Rick Copeland
 
Chef on Python and MongoDB
Rick Copeland
 
Real-Time Python Web: Gevent and Socket.io
Rick Copeland
 
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Rick Copeland
 
Realtime Analytics Using MongoDB, Python, Gevent, and ZeroMQ
Rick Copeland
 
Rapid, Scalable Web Development with MongoDB, Ming, and Python
Rick Copeland
 
Allura - an Open Source MongoDB Based Document Oriented SourceForge
Rick Copeland
 
MongoATL: How Sourceforge is Using MongoDB
Rick Copeland
 

Recently uploaded (20)

PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
Complete Network Protection with Real-Time Security
L4RGINDIA
 
PPTX
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
PPTX
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
PPTX
Building a Production-Ready Barts Health Secure Data Environment Tooling, Acc...
Barts Health
 
PPTX
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PDF
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
PDF
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PDF
Predicting the unpredictable: re-engineering recommendation algorithms for fr...
Speck&Tech
 
PPT
Interview paper part 3, It is based on Interview Prep
SoumyadeepGhosh39
 
PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PPTX
MSP360 Backup Scheduling and Retention Best Practices.pptx
MSP360
 
PPTX
✨Unleashing Collaboration: Salesforce Channels & Community Power in Patna!✨
SanjeetMishra29
 
PDF
SFWelly Summer 25 Release Highlights July 2025
Anna Loughnan Colquhoun
 
PDF
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
PDF
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Complete Network Protection with Real-Time Security
L4RGINDIA
 
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
WooCommerce Workshop: Bring Your Laptop
Laura Hartwig
 
Building a Production-Ready Barts Health Secure Data Environment Tooling, Acc...
Barts Health
 
AUTOMATION AND ROBOTICS IN PHARMA INDUSTRY.pptx
sameeraaabegumm
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Complete JavaScript Notes: From Basics to Advanced Concepts.pdf
haydendavispro
 
TrustArc Webinar - Data Privacy Trends 2025: Mid-Year Insights & Program Stra...
TrustArc
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
Predicting the unpredictable: re-engineering recommendation algorithms for fr...
Speck&Tech
 
Interview paper part 3, It is based on Interview Prep
SoumyadeepGhosh39
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
MSP360 Backup Scheduling and Retention Best Practices.pptx
MSP360
 
✨Unleashing Collaboration: Salesforce Channels & Community Power in Patna!✨
SanjeetMishra29
 
SFWelly Summer 25 Release Highlights July 2025
Anna Loughnan Colquhoun
 
CIFDAQ Token Spotlight for 9th July 2025
CIFDAQ
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
Empower Inclusion Through Accessible Java Applications
Ana-Maria Mihalceanu
 
LLMs.txt: Easily Control How AI Crawls Your Site
Keploy
 

Schema Design at Scale

  • 1. MongoDB: Schema Design at Scale Rick Copeland @rick446 http://arborian.com
  • 2. Who am I? • Now a consultant/trainer, but formerly... • Software engineer at SourceForge • Author of Essential SQLAlchemy • Author of MongoDB with Python and Ming • Primarily code Python
  • 3. The Inspiration • MongoDB monitoring service (MMS) • Free to all MongoDB users • Minute-by-minute stats on all your servers • Hardware cost is important, use it efficiently (remember it’s a free service!)
  • 4. Our Experiment • Similar to MMS but not identical • Collection of 100 metrics, each with per- minute values • “Simulation time” is 300x real time • Run on 2x AWS small instance • one MongoDB server (2.0.2) • one “load generator”
  • 5. Load Generator • Increment each metric as many times as possible during the course of a simulated minute • Record number of updates per second • Occasionally call getLastError to prevent disconnects
  • 6. Schema v1 { _id: "20101010/metric-1", metadata: { date: ISODate("2000-10-10T00:00:00Z"), metric: "metric-1" }, • One document daily: 5468426, hourly: { per metric (per "00": 227850, server) per day "01": 210231, ... "23": 20457 }, minute: { • Per hour/minute "0000": 3612, statistics stored as "0001": 3241, ... documents "1439": 2819 } }
  • 7. Update v1 • Use $inc to update fields in- place increment = { daily: 1 } increment['hourly.' + hour] = 1 increment['minute.' + minute] = 1 • Use upsert to db.stats.update( { _id: id, metadata: metadata }, create document { $inc: update }, if it’s missing true) // upsert • Easy, correct, seems like a good idea....
  • 9. Performance of v1 Experiment startup
  • 10. Performance of v1 Experiment startup OUCH!
  • 11. Problems with v1 • The document movement problem • The midnight problem • The end-of-the-day problem • The historical query problem
  • 12. Document movement problem • MongoDB in-place updates are fast • ... except when they’re not in place • MongoDB adaptively pads documents • ... but it’s better to know your doc size ahead of time
  • 13. Midnight problem • Upserts are convenient, but what’s our key? • date/metric • At midnight, you get a huge spike in inserts
  • 14. Fixing the document movement problem • Preallocate db.stats.update( documents with { _id: id, metadata: metadata }, zeros { $inc: { daily: 0, hourly.0: 0, hourly.1: 0, ... • Crontab (?) minute.0: 0, minute.1: 0, ... } • NO! (makes true) // upsert the midnight problem even worse)
  • 16. Fixing the midnight problem • Could schedule preallocation for different metrics, staggered through the day
  • 17. Fixing the midnight problem • Could schedule preallocation for different metrics, staggered through the day • Observation: Preallocation isn’t required for correct operation
  • 18. Fixing the midnight problem • Could schedule preallocation for different metrics, staggered through the day • Observation: Preallocation isn’t required for correct operation • Let’s just preallocate tomorrow’s docs randomly as new stats are inserted (with low probability).
  • 19. Performance with Preallocation Experiment startup
  • 20. Performance with Preallocation • Well, it’s better Experiment startup
  • 21. Performance with Preallocation • Well, it’s better • Still have Experiment startup decreasing performance through the day... WTF?
  • 22. Performance with Preallocation • Well, it’s better • Still have Experiment startup decreasing performance through the day... WTF?
  • 23. Problems with v1 • The document movement problem • The midnight problem • The end-of-the-day problem • The historical query problem
  • 24. End-of-day problem “0000” Value “0001” Value “1439” Value • Bson stores documents as an association list • MongoDB must check each key for a match • Load increases significantly at the end of the day (MongoDB must scan 1439 keys to find the right minute!)
  • 25. Fixing the end-of-day problem • { _id: "20101010/metric-1", metadata: { Split up our date: ISODate("2000-10-10T00:00:00Z"), metric: "metric-1" }, ‘minute’ property daily: 5468426, hourly: { by hour "0": 227850, "1": 210231, ... "23": 20457 }, • Better worst-case minute: { keys scanned: "00": { "0000": 3612, "0100": 3241, ... }, ..., • Old: 1439 "23": { ..., "1439": 2819 } } • New: 82
  • 29. Historical Query Problem • Intra-day queries are great • What about “performance year to date”? • Now you’re hitting a lot of “cold” documents and causing page faults
  • 30. Fixing the historical query problem • Store multiple levels { _id: "201010/metric-1", of granularity in metadata: { date: ISODate("2000-10-01T00:00:00Z"), different collections metric: "metric-1" }, • daily: { "0": 5468426, 2 updates rather than "1": ..., ... 1, but historical } "31": ... }, queries much faster • Preallocate along with daily docs (only infrequently upserted)
  • 31. Queries db.stats.daily.find( { • Updates are by "metadata.date": { $gte: dt1, $lte: dt2 }, "metadata.metric": "metric-1"}, _id, so no index { "metadata.date": 1, "hourly": 1 } }, needed there sort=[("metadata.date", 1)]) • Chart queries are by metadata db.stats.daily.ensureIndex({ 'metadata.metric': 1, • Your range/sort 'metadata.date': 1 }) should be last in the compound index
  • 32. Conclusion • Monitor your performance. Watch out for spikes. • Preallocate to prevent document copying • Pay attention to the number of keys in your documents (hierarchy can help) • Make sure your index is optimized for your sorts
  • 33. Questions? MongoDB Monitoring Service http://www.10gen.com/mongodb-monitoring-service Rick Copeland @rick446 http://arborian.com MongoDB Consulting & Training

Editor's Notes