2015-01-06 9 views
16

tworzę indeks MongoDB mającego 10 milionów płyt, ale po błędzieNie można utworzyć indeks MongoDB, „klucz zbyt duży do indeksu”

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 
} 

Proszę mi pomóc jak createindex w MongoDB,

+0

Próbujesz usunąć indeks dla "Module". Myślę, że Twoje treści są za duże, by wyświetlać zwykły indeks. – NHK

Odpowiedz

24

MongoDB nie utworzy indeksu dla kolekcji, jeśli pozycja indeksu dla istniejącego dokumentu przekroczy wartość index key limit (1024 bajty). Można jednak stworzyć hashed index lub text index zamiast:

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

lub

db.logcollection.ensureIndex({"Module":"text"}) 
+1

dziękuję, to działało dla mnie, ale wydajność indeksu bardzo powolnego, moje zapytanie to db.logcollection.find ({"Module": "RezGainUI"}). Count(). obliczenie –

+1

zajmuje około 18 sekund. Znajdź wartości długości i skróć je, jeśli możesz. Następnie możesz stworzyć normalny indeks – anhlc

+0

Przepraszam, jestem nowy w mongodb, proszę, poprowadź mnie, jak to zrobić –

13

Można milczeć to zachowanie poprzez uruchomienie mongod instancję za pomocą następującego polecenia:

mongod --setParameter failIndexKeyTooLong=false 

lub przez wykonanie następujące polecenie od mongoShell

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

Jeśli upewniłeś się, że twoje pole przekroczy limit bardzo rzadko, to jednym ze sposobów rozwiązania tego problemu jest podzielenie twojego pola (które powoduje indeks poza limit) na części według długości bajtowej < 1KB np. dla pola val podzieliłbym go na krotkę pól val_1, val_2 i tak dalej. Mongo przechowuje tekst jako prawidłowe wartości UTF-8. Oznacza to, że potrzebujesz funkcji, która poprawnie rozdzieli ciągi 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 

Następnie można zdefiniować indeks złożonych:

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

lub wiele indeksów za każdym 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}) 

Ważne: jeśli wziąć pod uwagę przy użyciu pola indeksu złożonego następnie uważaj na drugi argument funkcji split_utf8. Przy każdym dokumencie musisz usunąć sumę bajtów każdej wartości pola, która zawiera twój klucz indeksu, np. dla wskaźnika (A 1, B 1, Val: 1) 1024 - sizeof(value(a)) - sizeof(value(b))

W innych przypadkach używać zarówno hash lub text indeksów.

+0

Utworzenie dla tego indeksu złożonego nie zadziałałoby, ponieważ limit rozmiaru 1024 dotyczy całego [klucza indeksu] (https: // docs.mongodb.com/v3.2/reference/limits/#Index-Key-Limit), a nie w każdym polu. – JohnnyHK

+0

@JohnnyHK masz rację. Zobacz "Ważne" notatki. Udoskonaliłem to. –

+1

W moim projekcie mam indeksy 4-5 wymiarowe i to podejście działa lśniąco :) –

Powiązane problemy