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
'prosource' 카테고리의 다른 글
.NET MySql 커넥터를 사용하여 mariadb에서 DELMITER를 사용하는 방법은 무엇입니까? (0) | 2023.07.07 |
---|---|
Apache POI, 새 셀 작성이 행 스타일을 재정의합니다. (0) | 2023.07.07 |
PL-SQL의 contains()는 어떻게 작동합니까? (0) | 2023.07.07 |
한 컬렉션에서 다른 컬렉션으로 mongo 복사(같은 DB에 있음 (0) | 2023.07.07 |
R: c++/c#/sigma 등과 동등한 +=(+) 및 ++(+)? (0) | 2023.07.07 |