2016-09-21 4 views
0

В MongoDb имеется 32-битный тип int (4 байта) и 96-битный тип ObjectId (12 байт). Я заметил, что индекс в 32-битном int-поле больше, чем на поле ObjectId, тогда как я ожидал противоположного по этому вопросу: Are there any tools to estimate index size in MongoDB?Размер индекса MongoDB зависит от размера поля?

Это специфично для ObjectId и как это возможно?

Вот некоторые статистические данные, показывающие разницу, используя MongoDB 3.2.9 и MongoDB-драйвер Java-3.2 с конфигурацией по умолчанию (двигатель WiredTiger + мгновенным уровня сжатия)

"_id" как ObjectId:

> db.objectId.stats() 
{ 
    "ns" : "test1.objectId", 
    "count" : 500000, 
    "size" : 20500000, 
    "avgObjSize" : 41, 
    "storageSize" : 6737920, 
    [...] 
    "nindexes" : 1, 
    "totalIndexSize" : 4300800, 
    "indexSizes" : { 
     "_id_" : 4300800 
    } 
} 

"_id", как int32 (линейная вставка):

 > db.int32linear.stats() 
{ 
    "ns" : "test1.int32linear", 
    "count" : 500000, 
    "size" : 16500000, 
    "avgObjSize" : 33, 
    "storageSize" : 5586944, 
    [...] 
    "nindexes" : 1, 
    "totalIndexSize" : 5255168, 
    "indexSizes" : { 
     "_id_" : 5255168 
    } 
} 

"_id", как int32 (случайная вставка):

> db.int32random.stats() 
{ 
    "ns" : "test1.int32random", 
    "count" : 500000, 
    "size" : 16500000, 
    "avgObjSize" : 33, 
    "storageSize" : 5595136, 
    [...] 
    "nindexes" : 1, 
    "totalIndexSize" : 5378048, 
    "indexSizes" : { 
     "_id_" : 5378048 
    } 
} 

Вот код, чтобы воспроизвести тест:

import com.mongodb.MongoClient; 
import com.mongodb.client.MongoCollection; 
import com.mongodb.client.MongoDatabase; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import org.bson.Document; 

public class Main { 

    public static void main(String[] args) { 

     List<Document> listDoc = new ArrayList<>(); 

     MongoClient mongoClient = new MongoClient(); 
     MongoDatabase db = mongoClient.getDatabase("test1"); 

     MongoCollection<Document> objectId = db.getCollection("objectId"); 
     MongoCollection<Document> int32linear = db.getCollection("int32linear"); 
     MongoCollection<Document> int32random = db.getCollection("int32random"); 

     for(int i = 0; i<500000; i++){ 
      listDoc.add(new Document("field", "content")); 
     } 
     objectId.insertMany(listDoc); 
     listDoc.clear(); 

     for (int i = 0; i<500000; i++){ 
      listDoc.add(new Document("_id", i).append("field", "content")); 
     } 
     int32linear.insertMany(listDoc); 
     // unsort the array 
     Collections.shuffle(listDoc); 

     int32random.insertMany(listDoc); 

     mongoClient.close(); 

    } 
} 
+0

Какой двигатель хранения, WildTiger или mmap? Не ответ, а пара вещей, которые нужно попробовать: рандомизированное вместо упорядоченных значений int и удаление коллекции вместо удаления документов перед тестом, чтобы получить чистую начальную точку, поскольку могут быть свободные списки удаленных распределений, если вы просто удалите все записи. – user3973

+0

Это с двигателем wiredTiger. Я обновил тест в соответствии с вашим комментарием, но все равно получаю те же результаты (см. Мое редактирование). – felix

ответ

1

Я не уверен, но: WildTiger эффективно сжимать объект ID ключей , Если вы посмотрите, как они сгенерированы, и если все документы вставляются очень быстро (через несколько секунд), на одной машине будет очень длинный общий префикс идентификаторов объектов. При этом префикс ключа WildTiger будет довольно эффективным.

Так почему же это не работает с добавочными целыми числами? Из-за маленького формата endian.

Если вышеприведенная гипотеза верна, на практике в реальной системе, где время вставки больше разрывается и существует множество серверов (осколок), индекс ObjectId, вероятно, будет немного больше, чем индекс int, но все же довольно разумный в размере. Если вы хотите проверить это, попробуйте отключить сжатие при построении индекса.

В целом я думаю, что это хорошая новость, поскольку проблема заключается не в том, что индекс int большой, но что индекс ObjectId эффективен - ~ 10 байт/запись является разумным (хотя я мог бы представить, что лучше) является идентификатором записи в дополнение к ключу для каждого документа.

https://docs.mongodb.com/manual/reference/method/ObjectId/

P.S. Я полагаю, что инкрементный индекс int немного меньше, чем случайный, поскольку в mmap есть небольшая оптимизация для восходящих ключей.

+0

вы правы, если я отключу префикс Compression перед вставкой данных, размер индекса на int32linear не изменяется, но размер индекса на объекте Double double (" indexSizes ": {" _id_ ": 9818112})! Благодарим за освещение этого – felix