programing

개체 대신 UUID 사용MongoDB의 ID

yellowcard 2023. 3. 21. 21:50
반응형

개체 대신 UUID 사용MongoDB의 ID

성능상의 이유로 데이터베이스를 MySQL에서 MongoDB로 이행하고 있으며, MongoDB 문서의 ID에 사용할 것을 고려하고 있습니다.오브젝트 사용 여부를 검토 중입니다.ID(MongoDB 기본값) 또는 UUID 대신 사용(MySQL에서 지금까지 사용)지금까지 이러한 옵션 중 하나를 지원해야 하는 인수는 다음과 같습니다.

오브젝트 ID: 오브젝트ID는 MongoDB의 디폴트이며, (확실하지는 않지만) 이유가 있다고 생각합니다.즉, MongoDB가 UUID보다 효율적으로 ID를 처리할 수 있거나 ID를 선호하는 다른 이유가 있다고 생각합니다.오브젝트의 사용법을 나타내는 이 stackoverflow 답변도 찾았습니다.ID는 인덱스를 더욱 효율적으로 만들지만, 이 "효율성"이 어느 정도인지 몇 가지 지표가 있으면 좋을 것입니다.

UUID: UUID를 사용하는 것을 찬성하는 우리의 기본 논거는 UUID가 어떤 식으로든 거의 모든 데이터베이스에서 지원된다는 것입니다.즉, 어떤 이유로든 MongoDB에서 다른 것으로 전환하기로 결정하고 ID를 기반으로 DB에서 문서를 가져오는 API를 이미 가지고 있다면 ID는 그대로 유지될 수 있기 때문에 이 API의 클라이언트는 변경되지 않습니다.오브젝트를 사용하는 경우ID를 다른 DB로 마이그레이션하는 방법을 잘 모르겠습니다.

이러한 옵션 중 하나가 다른 옵션보다 더 나은지, 그 이유는 무엇인지에 대한 통찰력을 가진 사람이 있습니까?오브젝트 대신 MongoDB에서 UUID를 사용한 적이 있습니까?ID와 만약 그렇다면 어떤 장점/문제점에 부딪혔습니까?

Mongo에서 UUID를 사용하는 것은 확실히 가능하며 충분히 지원됩니다.예를 들어, Mongo 문서에는 필드의 일반적인 옵션 중 하나로 UUID가 나열됩니다.

고려 사항.

  • 퍼포먼스 – 다른 답변에서 언급했듯이 벤치마크에서 UUID를 사용하면 삽입의 퍼포먼스가 저하됩니다.측정된 최악의 경우(컬렉션에서 1,000만에서 2,000만 문서까지)의 속도가 약 2~3배 느립니다. 삽입 속도는 2,000(UUID)과 7,500(오브젝트)의 차이입니다.ID) 초당 문서 수.이는 큰 차이이지만 그 중요성은 전적으로 사용 사례에 달려 있습니다.한번에 수백만 개의 문서를 일괄 삽입할 예정입니까?제가 만든 대부분의 앱은 개별 문서를 삽입하는 것이 일반적입니다.같은 벤치마크에서 이 사용 패턴에 대한 차이는 훨씬 작습니다(6,250 - vs - 7,500; ~ 20%).대수롭지 않은..지구가 산산조각 나진 않았어요
  • 휴대성 – 다른 많은 DB 플랫폼에서는 UUID가 잘 지원되므로 휴대성이 향상됩니다.또는 UUID가 더 크기 때문에(더 많은 비트), 오브젝트를 다시 패키징할 수 있습니다.ID를 UUID의 '쉐이프'로 만듭니다.이 접근방식은 직접 이동성만큼 좋지는 않지만 기존 객체 간에 "매핑"할 수 있습니다.ID 및 UUID
  • 분산화 – UUID의 주요 세일즈 포인트 중 하나는 UUID가 보편적으로 고유하다는 것입니다.이를 통해 어디서든 분산된 방식으로 데이터를 생성할 수 있습니다(예: "다음" 값을 결정하기 위해 중앙 집중화된 진실 출처를 필요로 하는 것과 대조적으로).물론, Mongo Object ID도 이 혜택을 공언합니다.차이점은 UUID는 15년 이상 된 표준을 기반으로 하며 모든 플랫폼, 언어 등에서 거의 지원된다는 것입니다.따라서 데이터베이스와 상호 작용하지 않고 분리된 시스템에서 엔티티(또는 특히 관련 엔티티 세트)를 작성해야 할 경우 매우 유용합니다.ID와 외부 키를 사용하여 데이터 집합을 만든 다음 나중에 충돌 없이 전체 그래프를 데이터베이스에 쓸 수 있습니다.Mongo Object에서도 가능하지만ID를 생성하기 위한 코드를 찾거나 형식을 사용하는 작업은 종종 더 어려워집니다.

수정

다른 답변과 달리:

  • UUID는 네이티브 Mongo 지원– Mongo Shell의 기능을 사용할 때와 동일하게 사용할 수 있습니다.ObjectID(); UUID 문자열을 동등한 BSON 개체로 변환합니다.
  • UUID가 특별히 크지는 않다– 바이너리 서브 타입을 사용하여 인코딩된 경우0x04오브젝트의 96비트에 비해 128비트입니다.ID(문자열로 인코딩할 경우 약 288비트가 소요되므로 상당히 낭비됩니다.)
  • UUID에는 타임스탬프를 포함할 수 있습니다.구체적으로는 UUIDv1은 오브젝트 내의 32비트와 비교하여 60비트의 정밀도로 타임스탬프를 부호화합니다.ID. 10진수에서는 6배 이상의 정밀도를 얻을 수 있습니다.즉, 초가 아닌 나노초입니다.실제로는 작성 타임스탬프를 Mongo/JS Date 객체가 지원하는 것보다 더 정확하게 저장하는 적절한 방법이 될 수 있습니다.
    • UUID()이 함수는 v4(랜덤) UUID만 생성하므로 이를 활용하려면 앱이나 Mongo 드라이버에 의존하여 ID를 생성해야 합니다.
    • 오브젝트와는 다른ID, UUID가 청크되는 방식 때문에 타임스탬프는 자연스러운 순서를 제공하지 않습니다.이것은 사용 사례에 따라 좋을 수도 있고 나쁠 수도 있습니다.(새로운 규격에 의해 변경될 수 있습니다.아래 2021 업데이트 참조).
    • ID에 타임스탬프를 포함하는 것은 좋지 않은 생각이 될 수 있습니다.ID가 노출되면 문서 작성 시간이 유출됩니다.(물론 객체)ID는 타임스탬프도 부호화하기 때문에, 이것은 부분적으로 그들에게도 해당됩니다).
    • (스펙 준거) v1 UUID를 사용하면 서버 MAC 주소의 일부도 인코딩되므로 머신을 식별하는 데 사용할 수 있습니다.대부분의 시스템에서 문제가 되지 않을 뿐만 아니라 이상적이지 않을 수 있습니다.(새로운 규격에 의해 변경될 수 있습니다.아래 2021 업데이트 참조).

결론

Mongo DB를 분리하여 생각하면 오브젝트ID는 명백한 선택입니다.이들은 개봉 후 바로 사용할 수 있으며 완벽하게 사용할 수 있는 기본값입니다.대신 UUID를 사용하면 값 사용 시(바이너리 유형으로 변환해야 함 등) 및 성능 측면에서 마찰이 발생합니다.이 약간의 불편함이 표준화된 ID 형식을 가질 가치가 있는지 여부는 휴대성과 아키텍처 선택에 대한 중요성에 따라 결정됩니다.

서로 다른 데이터베이스 플랫폼 간에 데이터를 동기화합니까?향후 다른 플랫폼으로 데이터를 이행할 예정입니까?데이터베이스 외부, 다른 시스템 또는 브라우저에서 ID를 생성해야 합니까?미래의 어느 시점에 있지 않다면?UUID는 번거롭게 할 가치가 있습니다.

2021년 8월 갱신

IEFT는 최근 UUID 사양에 대한 새로운 버전의 포맷을 도입하는 초안 업데이트를 발표했습니다.

특히 UUIDv6UUIDv7은 UUIDv1을 기반으로 하지만 비트가 최상위부터 최하위까지 정렬되도록 타임스탬프 청크를 플립합니다.이로 인해 결과 값은 생성된 순서를 반영하는 자연스러운 순서를 얻을 수 있습니다.새로운 버전에서는 서버의 MAC 주소에서 파생된 데이터도 제외되어 v1 UUID에 대한 오랜 비판에 대처하고 있습니다.

이러한 변경이 구현에 반영되려면 시간이 걸리겠지만 (IMHO) 포맷을 상당히 현대화하고 개선합니다.

_idMongoDB 필드에는 원하는 값을 지정할 수 있습니다.단, 컬렉션에 대해 고유함을 보증할 수 있으면 됩니다.키가 경우 된 Object 이 이유가 .

키를 의 위해)을 위한 됩니다.ID는 자체 고유 키를 생성하는 안전한 시간(또한 초보자가 SQL을 복사하지 않도록 하기 위해)을 위한 합리적인 기본 솔루션으로 제공됩니다.AUTO INCREMENT분산형 데이터베이스에서는 좋지 않은 생각입니다).

를 하지 않음 다른 기능에서도 。[ ] 、 [ ] 、 [ ] 、 [ ID : ]ID에는 생성 시 Unix 타임스탬프도 포함되어 있으며, 많은 드라이버는 이 타임스탬프를 추출하여 날짜로 변환하는 함수를 제공합니다. 수 있습니다.create-date필드 용장성

어느 가 되지 않는 를 UUID로 롭게 사용할 수 ._idsyslog.syslog.syslog.

각 경우에 저장할 데이터의 양을 고려합니다.

MongoDB 오브젝트ID의 크기는 12바이트이며, 저장용으로 포장되어 있으며, ID의 부품은 성능을 위해 구성되어 있습니다(즉, 먼저 타임스탬프가 저장되며, 이는 논리적 순서 기준입니다).

반대로 표준 UUID는 36바이트로 대시를 포함하며 일반적으로 문자열로 저장됩니다.또한 숫자가 아닌 문자를 제거하고 숫자로 저장하려는 경우에도 UUID의 "indexy" 부분(타임스탬프 기반 UUID v1의 일부)이 UUID의 중간에 있으므로 정렬에 적합하지 않은 것으로 만족해야 합니다.퍼포먼스 UUID 스토리지를 가능하게 하는 연구도 행해졌고, 그 관리를 지원하기 위해 Node.js 라이브러리도 작성했습니다.

UUID를 사용하려는 경우 최적의 인덱싱 및 정렬을 위해 UUID를 재구성하는 것이 좋습니다. 그렇지 않으면 성능 벽에 부딪힐 수 있습니다.

MongoDB의 삽입 비용과 처음부터 제품을 생성하는 비용과 페이로드의 크기에 따른 비용을 구분하는 데 주의해야 합니다.아래는 이 명령어를 생성하는 방법을 보여 주는 작은 매트릭스입니다._idpayload payload payload payload payload payload payload payload 。 Pro 에서 "javascript", "MacBook Pro 100,000"을 사용하여 100합니다.insertMany네트워크, 채팅 및 기타 요소를 삭제하기 위해 트랜잭션 없이 100개의 배치로 구성됩니다.배치 = 1인 두 번의 런도 극적인 차이를 강조하기 위해 수행되었습니다.


Method                                                                                         
A  :  Simple int:          _id:0, _id:1, ...                                                   
B  :  ObjectId             _id:ObjectId("5e0e6a804888946fa61a1976"), ...                       
C  :  Simple string:       _id:"A0", _id:"A1", ...                                             

D  :  UUID length string   _id:"9575edcc-cb70-4d63-97ed-ee5d624de87b0", ...                    
      (but not actually                                                                        
      generated by UUID()                                                                      

E  :  Real generated UUID  _id: UUID("35992974-21ea-4f61-b715-2dfaed663b73"), ...              
      (stored UUID() object)                                                                   

F  :  Real generated UUID  _id: "6b16f733-ff24-4172-83f9-e4f96ace6775"                         
      (stored as string, e.g.                                                                  
      UUID().toString().substr(6,36)                                                           

Time in milliseconds to perform 100,000 inserts on fresh (empty) collection.

Extra                M E T H O D   (Batch = 100)                                                               
Payload   A     B     C     D     E     F       % drop A to F                                  
--------  ----  ----  ----  ----  ----  ----    ------------                                   
None      2379  2386  2418  2492  3472  4267    80%                                            
512       2934  2928  3048  3128  4151  4870    66%                                            
1024      3249  3309  3375  3390  4847  5237    61%                                            
2048      3953  3832  3987  4342  5448  5888    49% 
4096      6299  6343  6199  6449  7634  8640    37%                                            
8192      9716  9292  9397 10816 11212 11321    16% 

Extra              M E T H O D   (Batch = 1)                                          
Payload   A      B      C      D      E      F       % drop A to F              
--------  -----  -----  -----  -----  -----  -----                              
None      48006  48419  49136  48757  50649  51280   6.8%                       
1024      50986  50894  49383  49373  51200  51821   1.2%                       


이것은 는 ints로 되어 것이 ._id속도는 거의 동일하지만 실제로 UUID를 생성하면 시간이 추가됩니다.특히 문자열 버전의 UUID를 사용하면UUID() 오 object:UUID().toString().substr(6,36)또, 이 테크놀로지의 구축에 주의할 필요가 있습니다.ObjectId빠른 것 같습니다.

나는 지난 몇 주 동안 이것에 대해 생각해 왔다.ObjectId와 UUID는 둘 다 고유하다는 것을 알게 되었습니다.실제로 컬렉션 수준에서는 사용하는 유형에 관계없이 중복된 _id를 가질 수 없습니다.일부 답변은 삽입 성능에 대해 언급했습니다.중요한 것은 삽입 퍼포먼스가 아니라 인덱스 퍼포먼스입니다.이 값은 _ids 인덱스에 사용하는 RAM의 양에 따라 계산해야 합니다.ObjectId는 12바이트이며 UUID는 36바이트입니다.ObjectId 대신 UUID를 사용하면 동일한 양의 인덱스에 2배의 RAM 공간이 필요하다고 합니다.

따라서 mongodb에서는 ObjectId를 UUID보다 사용하는 것이 좋습니다.

UUID128비트(16바이트)로 글로벌하게 일의입니다.RFC 4122참조해 주세요.

Object Ids이며 MongoDB입니다.96비트(12바이트)또한 글로벌하게 고유성을 제공하기에 충분하지만 몇 가지 엣지 조건이 있습니다.MongoDB는 이 을 비교하기 위한 공식 문서를 가지고 있습니다.

MongoDB 고유의 ID 생성에 얽매이지 않고 클라이언트 측에서 하는 것을 선호합니다.또한 여러 종류의 데이터베이스를 사용합니다.부터 말하면, 「 」 「 」를 합니다.UUID에 걸쳐서ObjectId특정 사용 사례에 따라 결정할 수 있습니다.

저는 얼마 전에 같은 질문을 받았을 때 이 벤치마크들을 발견했습니다.기본적으로 ObjectId 대신 GUID를 사용하면 인덱스 퍼포먼스가 저하된다는 것을 알 수 있습니다.

어쨌든 벤치마크를 커스터마이즈하여 구체적인 실제 시나리오를 모방하고 수치가 어떻게 표시되는지 보는 것이 좋습니다.일반적인 벤치마크에 100% 의존할 수는 없습니다.

이거 드셔보세요

    const uuid = require('uuid')
const mongoose = require('mongoose')
const YourSchema = new Schema({
  _id:{
    type: String,
        default: () => uuid.v4().replace(/\-/g, ""), 
   }


})

언급URL : https://stackoverflow.com/questions/28895067/using-uuids-instead-of-objectids-in-mongodb

반응형