
MongoDB 5.0 부터 새롭게 도입 된 Time Series Collections
MongoDB 4.4에서 5.0으로 업그레이드 하기 를 통해서 MongoDB 5.0을 사용할 준비가 되었습니다. 그러면 이제 MongoDB 5.0에서 지원하는 새로운 기능을알아보겠습니다. Time SeriesData란? 정적 데이터가 아닌, 시간에 따라 값이 변하는 데이터를말합니다. 대신 변하는 값 이 외에 저장되는 데이터의 변화는미미합니다. 예시로 IoT Sensor에서 주기적으로 전달하는 데이터, 시간에 따른 날씨 데이터, 자동차 경로 추적 데이터 그리고 주식 또는 가상자산 시세 데이터 등이있습니다. Time Series Collection의 개념 기존 Collection의 동작방식 이런 Time Series 데이터들은 식별자와 시간을 조건으로 검색해서 사용하는 경우가대부분입니다. 그렇기에 아래와 같이 디스크의 여러 블록에 저장되면, 인덱스를 걸어서 흩어져 있는 데이터를 빠르게 읽을 수 있도록합니다. 하지만 인덱싱을 통해서 데이터 읽기 시간을 줄이는 것도 한계와 단점이 있습니다. 데이터가 많아질 수록 더 많은 블록에 흩어지게 될 것이고, 그로 인해 더 많은 인덱스 크기는 점점 더 커지게 될것입니다. Time Series Collection의 동작방식 Time Series Collection은 이러한 한계를 보완하기 위해서, Collection 생성 시 timeField와 metaField를 미리지정합니다. 그리고 metaField가 동일한 데이터를 동일한(또는 인접한) 블록에 저장시켜, 액세스 시간을 획기적으로줄입니다. 그와 더불어 인덱스 크기도 저장되는 블록 수가 줄어듦에 따라 같이 줄어들게됩니다. Time Series 내부 저장방식 Collection 생성방법 날씨 데이터를 저장하기 위한 Time Series Collection 예시 db.createCollection("weather", ( timeseries: ( timeField: "timestamp", metaField: "source", granularity: "seconds" ) )) // source : ( stationId, station ) 저장되는 데이터구조 Metadata, Measurements, Internal 데이터로 나뉘어저장 Metadata: 변하지 않는 값으로 한 번만저장 Measurements: 동일한 항목을 모아서 배열로저장 Internal: 기타 내부적으로 데이터 관리에 필요한 정보를저장 Best Practices 데이터 쓰기 시 insertMany에 ( ordered: false ) 옵션을 넘겨 일괄쓰기하는 것이 최대 성능을 이끌어냅니다. metaField를 지정하고, Query 패턴에 맞춰 secondaryIndex를 생성합니다. Use Case(데이터 생성 빈도)에 맞게 granularity 설정 (seconds, minutes, hours)합니다. granularity는 기본 값으로 seconds로 설정되며, collection 생성 이후에도 변경 가능합니다. 단, 작은 단위에서 큰 단위로만 변경이 가능할 뿐 그 반대의 경우는 불가능합니다. (seconds -> minutes -> hours 가능, hours -> minutes -> seconds 불가능) 그렇기 때문에 처음엔 seconds로 생성하고, 추후에 데이터 빈도에 맞게 조정하는 것을추천합니다. 다음으로 실제 Collection을 생성하고, 데이터 쓰기와 읽기를 진행해보겠습니다. Time Series Collection 지원 여부확인 우선 사용 중인 MongoDB가 Time Series Collection을 지원하는지 확인해 봐야합니다. Time Series Collection은 MongoDB 5.0 부터 지원하기에 아래 명령을 통해서 featureCompatibilityVersion이 5.0으로 설정되어 있는지 확인합니다. (Robo3T의 Shell을 통해서실행했습니다.) db.adminCommand(( getParameter:1, featureCompatibilityVersion: 1 )) 아래 처럼 version에 5.0이 표시되어 있어야합니다. 만약 4.4 등 다른 버전이 표시되어 있다면, 아래 명령을 통해서 5.0으로설정합니다. db.adminCommand( ( setFeatureCompatibilityVersion: ř.0" ) ) 혹시 해당 명령 실행 시 권한이 없다는 에러 메시지가 나온다면, root 권한이 있는 계정으로 다시 접속하여진행합니다. Time Series Collection 생성 Mongoose를 사용하는 경우 일반적인 경우 명시적으로 Collection을 생성하지 않고, 데이터 쓰기를 통해서 Collection을 생성하곤합니다. Time Series 데이터도 동일하게 적용이 될까요? 그렇지 않습니다. 데이터 쓰기를 통해서 Collection을 생성하게 되면, 일반 collection type으로 생성이됩니다. 아래 명령을 통해서 collection의 type을 확인할 수있습니다. db.runCommand( ( listCollections: 1.0 ) ) 그렇기에 반드시 명시적으로 collection을 생성한 후 사용해야합니다. db.createCollection('gd_energy_heating_condition', ( timeseries: ( timeField: 'createdAt', metaField: 'metadata', granularity: 'hours', ) )) 생성 후 collection type을 확인하면 timeseries로 되어있습니다. 데이터 쓰기 데이터 쓰기의 최대 성능을 이끌어 내기 위해서는 insertMany를 사용해야합니다. 사용자가 입력하는 데이터 순서가 아니라, Time Series 규칙에 따라 순서를 정해야 하기에 ordered: false 옵션을 설정해야합니다. db.getCollection('gd_energy_heating_condition').insertMany([( metadata: ( company: �aab6722f001c951759', workplace: �b6722f001c95175a', ), temperature: 36.5, createdAt: ISODate(-02-24 09:03:45.000Z'), ), ( metadata: ( company: �aab6722f001c951759', workplace: �b6722f001c95175a', ), temperature: 36.3, createdAt: ISODate(-02-24 10:03:45.000Z'), ), ( metadata: ( company: �aab6722f001c951759', workplace: �b6722f001c95175b', ), temperature: 136.5, createdAt: ISODate(-02-24 09:03:45.000Z'), ), ( metadata: ( company: �aab6722f001c951759', workplace: �b6722f001c95175b', ), temperature: 136.3, createdAt: ISODate(-02-24 10:03:45.000Z'), )], ( ordered: false )) 데이터 읽기 저장되어 있는 데이터의 형태는 일반 Collection과 다를게없습니다. Query, Aggregate도 일반 Collection과 동일하게 사용하면됩니다. db.getCollection('gd_energy_heating_condition').aggregate([ ( $project: ( company: '$metadata.company', workplace: '$metadata.workplace', date: ( $dateToParts: ( date: "$createdAt", timezone: 'Asia/Seoul' ) ), temperature: 1 ) ), ( $group: ( _id: ( company: '$company', workplace: '$workplace', date: ( year: '$date.year', month: '$date.month', day: '$date.day' ) ), avgTemperature: ( $avg: "$temperature" ) ) ) ]) 성능 비교 간단한 주식 가격 정보 데이터 30만 건을 저장하고 timestamp로 검색한 결과입니다. (출처: https://www.percona.com/blog/mongodb-5-0-time-series-collections/) 적은 양의 데이터를 가지고 테스트한 것이기 때문에 차이가 과장되게 날 수있습니다. 데이터 저장용량 Time Series Collection이 Regular Collection의 약 1/4크기 Time Series Collection: 5,357,568 bytes Regular Collection: 21,934,080 bytes 데이터 읽기 속도 (간단한Query) Time Series Collection이 Regular Collection보다 100배 가량빠름 Time Series Collection: 2ms Regular Collection: 200ms 데이터 읽기 속도 (조금 복잡한 Aggregation) Time Series Collection이 Regular Collection 보다 약 40% 가량빠름 Time Series Collection: 615ms Regular Collection: 1022ms 마무리 IoT 데이터를 많이 사용하고 있는 한국그린데이터의 경우 Time Series Collection을 도입하는 것이 비용적인 측면과 성능적인 측면에서 모두 이득이 된다고 볼 수있습니다. 이 밖에 expireAfterSeconds를 지정해서 자동으로 데이터를 정리한다거나, Windows Functions를 활용하여 보다 효율적인 Query 생성이 가능할 것으로보입니다. 추후에 더 연구하여 공유하도록하겠습니다. 참고 Time Series Collections Migrate Data into a Time Series Collection Its About Time: From IoT to Finance, working with time series data inMongoDB Paginations 1.0 — A Brief Introduction to Time Series Collections Paginations 1.0: Time Series Collections in fiveminutes Purpose Built Optimizations for Time Series Workloads inMongoDB MongoDB 5.0 Time Series Collections MongoDB 5.0 부터 새롭게 도입 된 Time Series Collections was originally published in GreenDataKR on Medium, where people are continuing the conversation by highlighting and responding to this story.
