2012-01-28 5 views
2

Для поля, которое функционирует как счетчик, то есть значение будет изменено с течением времени и будет использоваться для возврата упорядоченных объектов (будет сортироваться против этого поля для фильтрованных объектов), мы должны построить индекс для этого поля?Строка индекса против полей счетчика

ответ

4

Это не совсем понятно, но я думаю, вопрос заключается в том, будут ли недостатки создания индекса в часто обновляемом поле перевешивают преимущества быстрого запроса и сортировки в этом поле. Вы также подразумеваете, что ваш запрос будет фильтроваться в другом поле, а затем вы хотите сортировать в этом поле. Не стесняйтесь подробно рассказать о своем конкретном случае использования.

То, что я думаю, что вы хотите что-то вроде этого:

db.test.save({filter: "stuff", count: "1"}); 
db.test.save({filter: "stuff", count: "3"}); 
db.test.save({filter: "stuff", count: "2"}); 
db.test.save({filter: "notstuff", count: "2"}); 
db.test.save({filter: "notstuff", count: "2"}); 

И тогда индекс так:

db.test.ensureIndex({filter:1, count:1}); 

А потом запрос так:

db.test.find({filter:"stuff"}).sort({count:1}); 
{ "_id" : ObjectId("4f24353eef88b8b53a20fdf5"), "filter" : "stuff", "count" : "1" } 
{ "_id" : ObjectId("4f24353eef88b8b53a20fdf7"), "filter" : "stuff", "count" : "2" } 
{ "_id" : ObjectId("4f24353eef88b8b53a20fdf6"), "filter" : "stuff", "count" : "3" } 

Какие использует btree:

db.test.find({filter:"stuff"}).sort({count:1}).explain(); 
{ 
"cursor" : "BtreeCursor filter_1_count_1", 
"nscanned" : 3, 
"nscannedObjects" : 3, 
... 

Теперь это может зависеть от того, сколько результатов вам нужно вернуть. Если это всего лишь несколько результатов, вы, вероятно, можете отсортировать поле без индекса, и это улучшит производительность обновления. Думаю, я действительно сделаю несколько тестов, так как мне любопытно. Я немного обновлю.

update Я написал этот тест, чтобы показать разницу между сортировкой по индексу и нет, и обновлением поля счета по индексу, а не. Полный код здесь: https://gist.github.com/1696041

Вставляет документы 700K и 7M (для получения разнообразия), разделенные на 7 "фильтров". Затем он произвольно выбирает документ, чтобы увеличить счет 1M раз. 1M docs на фильтр слишком велики для сортировки без ограничения, поэтому единственный способ показать, как работает эта штука, - это установить предел.

Вывод такой, как ожидалось. Это займет больше времени (почти в два раза длиннее в этом тесте - но в два раза больше - все еще довольно быстро), чтобы обновить поле count, когда на нем есть индекс. Но это гораздо быстрее, чем запрос. Вы должны решить, что для вас важнее.

Выход здесь (работает на моем Macbook Pro ж/SSD):

> bench(); 
benchmarking with index on {filter,data}, 700K docs 
initialInsert of 700000 done in: 58304ms, 0.08329142857142857ms per insert 
updateCounts 1000000 times done in: 103915ms, 0.103915ms per update 
explain find({filter:"abcd"}).sort({count:-1}): 
    cursor: BtreeCursor filter_1_data_1 
    nscanned: 100000 
    scanAndOrder: true 
    millis: 1235 
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
    cursor: BtreeCursor filter_1_data_1 
    nscanned: 100000 
    scanAndOrder: true 
    millis: 614 
benchmarking with index on {filter,data} and {filter, count}, 700k docs 
initialInsert of 700000 done in: 72108ms, 0.10301142857142857ms per insert 
updateCounts 1000000 times done in: 202778ms, 0.202778ms per update 
explain find({filter:"abcd"}).sort({count:-1}): 
    cursor: BtreeCursor filter_1_count_-1 
    nscanned: 100000 
    scanAndOrder: undefined 
    millis: 139 
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
    cursor: BtreeCursor filter_1_count_-1 
    nscanned: 100 
    scanAndOrder: undefined 
    millis: 0 
benchmarking with index on {filter,data}, 7M docs 
initialInsert of 7000000 done in: 616701ms, 0.08810014285714286ms per insert 
updateCounts 1000000 times done in: 134655ms, 0.134655ms per update 
explain find({filter:"abcd"}).sort({count:-1}): 
***too big to sort without limit!*** 
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
    cursor: BtreeCursor filter_1_data_1 
    nscanned: 1000000 
    scanAndOrder: true 
    millis: 6396 
benchmarking with index on {filter,data} and {filter, count}, 7M docs 
initialInsert of 7000000 done in: 891556ms, 0.12736514285714284ms per insert 
updateCounts 1000000 times done in: 280885ms, 0.280885ms per update 
explain find({filter:"abcd"}).sort({count:-1}): 
    cursor: BtreeCursor filter_1_count_-1 
    nscanned: 1000000 
    scanAndOrder: undefined 
    millis: 1337 
explain find({filter:"abcd"}).limit(100).sort({count:-1}): 
    cursor: BtreeCursor filter_1_count_-1 
    nscanned: 100 
    scanAndOrder: undefined 
    millis: 0 
+0

Это настолько велико, подробного объяснения. То, что вы ответили, именно то, о чем я хотел спросить. Следующий вопрос: существует ли верхний предел, который может быть отсортирован по количеству объектов? Есть ли для этого ориентир? – tom

+0

С индексом нет предела - вы можете сортировать всю коллекцию. И это не займет много времени, так как это то, что делают b-деревья. Предел для сортировки неиндексированного поля, по-видимому, составляет 4 МБ данных, согласно документам mongodb. –

0

Странный вопрос. Индексы используются для эффективных запросов. Если вы запрашиваете поле, и вы, скорее всего, заинтересованы, создайте индекс. explain() сообщает вам о плане выполнения. Все это подробно описано в документации MongoDB ... так почему вы задаете такой очень простой вопрос?