prosource

mongodb에 색인을 만들 수 없습니다. "키가 너무 커서 색인화할 수 없습니다."

probook 2023. 7. 7. 19:06
반응형

mongodb에 색인을 만들 수 없습니다. "키가 너무 커서 색인화할 수 없습니다."

mongodb에서 1000만 개의 레코드를 가진 인덱스를 만들고 있지만 오류가 발생했습니다.

db.logcollection.ensureIndex({"Module":1})
{
        "createdCollectionAutomatically" : false,
        "numIndexesBefore" : 3,
        "ok" : 0,
        "errmsg" : "Btree::insert: key too large to index, failing play.logcollection.$Module_1 1100 { : \"RezGainUISystem.Net.WebException: The request was aborted: The request was canceled.\r\n   at System.Net.ConnectStream.InternalWrite(Boolean async, Byte...\" }",
        "code" : 17282
}

mongodb에서 인덱스를 만드는 방법을 도와주세요.

기존 문서의 인덱스 항목이 인덱스 키 제한(1024바이트)을 초과하는 경우 MongoDB는 컬렉션에 인덱스를 작성하지 않습니다.그러나 해시 인덱스 또는 텍스트 인덱스를 대신 작성할 수 있습니다.

db.logcollection.createIndex({"Module":"hashed"})

또는

db.logcollection.createIndex({"Module":"text"})

다음 명령을 사용하여 mongod 인스턴스를 시작하여 이 동작을 중지할 수 있습니다.

mongod --setParameter failIndexKeyTooLong=false

또는 mongoShell에서 다음 명령을 실행하여

db.getSiblingDB('admin').runCommand( { setParameter: 1, failIndexKeyTooLong: false } )

필드가 제한을 초과하는 경우가 매우 드물다면 필드를 바이트 길이 < 1KB(예: 필드의 경우 인덱스가 제한을 벗어남)별로 분할하여 이 문제를 해결하는 방법이 있습니다.val나는 그것을 두 개의 들판으로 나눌 것입니다.val_1,val_2등등.Mongo는 텍스트를 utf-8 유효 값으로 저장합니다.utf-8 문자열을 제대로 분할할 수 있는 기능이 필요하다는 뜻입니다.

   def split_utf8(s, n):
    """
    (ord(s[k]) & 0xc0) == 0x80 - checks whether it is continuation byte (actual part of the string) or jsut header indicates how many bytes there are in multi-byte sequence

    An interesting aside by the way. You can classify bytes in a UTF-8 stream as follows:

    With the high bit set to 0, it's a single byte value.
    With the two high bits set to 10, it's a continuation byte.
    Otherwise, it's the first byte of a multi-byte sequence and the number of leading 1 bits indicates how many bytes there are in total for this sequence (110... means two bytes, 1110... means three bytes, etc).
    """
    s = s.encode('utf-8')
    while len(s) > n:
        k = n
        while (ord(s[k]) & 0xc0) == 0x80:
            k -= 1
        yield s[:k]
        s = s[k:]
    yield s

그런 다음 복합 인덱스를 정의할 수 있습니다.

db.coll.ensureIndex({val_1: 1, val_2: 1, ...}, {background: true})

또는 각 인덱스당 여러 개val_i:

db.coll.ensureIndex({val_1: 1}, {background: true})
db.coll.ensureIndex({val_1: 2}, {background: true})
...
db.coll.ensureIndex({val_1: i}, {background: true})

중요:만약 당신이 당신의 필드를 복합 인덱스에 사용하는 것을 고려한다면, 다음의 두 번째 인수를 조심하세요.split_utf8기능.각 문서에서 인덱스 키를 구성하는 각 필드 값의 바이트 합계를 제거해야 합니다(예: 인덱스(a:1, b:1, val:1).1024 - sizeof(value(a)) - sizeof(value(b))

다른 경우에는 해시 또는 텍스트 색인을 사용합니다.

다른 사람들이 답에서 지적했듯이, 오류는key too large to index필드 또는 필드의 길이가 1024바이트를 초과하는 인덱스를 작성하려고 한다는 의미입니다.

ASCII 용어로 1024바이트는 일반적으로 약 1024자로 변환됩니다.

MongoDB Limits and Thresholds 페이지에서 언급한 대로 MongoDB에서 설정한 고유 제한이므로 이에 대한 해결책은 없습니다.

BSON 유형에 따라 구조적 오버헤드를 포함할 수 있는 인덱스 항목의 총 크기는 1024바이트 미만이어야 합니다.

전원 켜기failIndexKeyTooLong오류는 서버 매개 변수 설명서 페이지에서 언급한 대로 해결책이 아닙니다.

...이러한 작업을 수행하면 문서를 삽입하거나 수정할 수 있지만 인덱스에는 문서에 대한 참조가 포함되지 않습니다.

이 문장은 위반 문서가 색인에 포함되지 않고 쿼리 결과에서 누락될 수 있다는 것을 의미합니다.

예:

> db.test.insert({_id: 0, a: "abc"})

> db.test.insert({_id: 1, a: "def"})

> db.test.insert({_id: 2, a: <string more than 1024 characters long>})

> db.adminCommand( { setParameter: 1, failIndexKeyTooLong: false } )

> db.test.find()
{"_id": 0, "a": "abc"}
{"_id": 1, "a": "def"}
{"_id": 2, "a": <string more than 1024 characters long>}
Fetched 3 record(s) in 2ms

> db.test.find({a: {$ne: "abc"}})
{"_id": 1, "a": "def"}
Fetched 1 record(s) in 1ms

가 MongoDB를 으로써 (MongoDB).failIndexKeyTooLong오류, 마지막 쿼리에 문제가 되는 문서(즉, 다음을 포함하는 문서)가 포함되어 있지 않습니다._id: 2결과에서 누락됨). 따라서 쿼리에서 잘못된 결과 집합이 발생했습니다.

인덱스제한에 도달하면 스키마의 필요에 따라 솔루션이 달라집니다.매우 드문 경우지만 1024바이트 이상의 값에 대한 키 일치가 설계 요구사항입니다.실제로 거의 모든 데이터베이스는 인덱스 키 제한을 적용하지만 일반적으로 레거시 관계형 DB(Oracle/MySQL/Postgre)에서 어느 정도 구성 가능합니다.SQL)을 사용하여 쉽게 자신의 발을 쏠 수 있습니다.

빠른 검색을 위해 "텍스트" 색인은 긴 텍스트 필드에서 검색 및 패턴 일치를 최적화하도록 설계되었으며 사용 사례에 적합합니다.그러나 일반적으로 긴 텍스트 값에 대한 고유성 제약 조건이 필요합니다.그리고 "텍스트" 인덱스는 고유한 플래그 집합이 있는 고유한 스칼라 값처럼 작동하지 않습니다.{ unique: true }(필드의 모든 텍스트 문자열 배열에 더 가깝습니다.)

MongoDb의 GridFS에서 영감을 얻은 고유성 검사는 문서에 "md5" 필드를 추가하고 그에 대한 고유한 스칼라 인덱스를 만들면 쉽게 구현할 수 있습니다.일종의 사용자 정의 고유 해시 인덱스입니다.이를 통해 검색을 위해 인덱싱되고 컬렉션 전체에서 고유한 텍스트 필드 길이를 거의 무제한(~16MB)으로 설정할 수 있습니다.

const md5 = require('md5');
const mongoose = require('mongoose');

let Schema = new mongoose.Schema({
  text: {
    type: String,
    required: true,
    trim: true,
    set: function(v) {
        this.md5 = md5(v);
        return v;
    }
  },
  md5: {
    type: String,
    required: true,
    trim: true
  }
});

Schema.index({ md5: 1 }, { unique: true });
Schema.index({ text: "text" }, { background: true });

제 경우에는 큰 하위 문서 배열에서 인덱스를 작성하려고 했습니다. 제가 가서 쿼리를 살펴보니 쿼리는 실제로 하위 속성의 하위 속성에 대한 것이었기 때문에 해당 하위 속성에 초점을 맞추도록 인덱스를 변경했고 제대로 작동했습니다.

저 같은 경우에는.goals한 "large" 큰 문서 "key too large" 는 " 큰하문키고었", " 패너큰무은다"처럼 보였습니다.{"goals": 1, "emailsDisabled": 1, "priorityEmailsDisabled": 1}질문은 다음과 같습니다.

emailsDisabled: {$ne: true},
priorityEmailsDisabled: {$ne: true},
goals: {
  $elemMatch: {
    "topPriority.ymd": ymd,
  }
}

▁be로 바꿨습니다.{"goals.topPriority.ymd": 1, "emailsDisabled": 1, "priorityEmailsDisabled": 1}그것은 잘 작동했습니다.

제가 여기서 성공했다고 확신하는 것은 인덱스를 만들 수 있다는 것입니다.해당 인덱스가 해당 쿼리에 대해 작동하는지에 대한 질문은 아직 답변하지 않은 별도의 질문입니다.

언급URL : https://stackoverflow.com/questions/27792706/cannot-create-index-in-mongodb-key-too-large-to-index

반응형