Построить индекс по счетчикам полей - PullRequest
2 голосов
/ 28 января 2012

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

Ответы [ 2 ]

4 голосов
/ 28 января 2012

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

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

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});

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

* * 1010

Который использует 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 раз. Документы 1М на фильтр слишком велики, чтобы их можно было сортировать без ограничений, поэтому единственный способ показать, как работает этот фрагмент, - это ввести ограничение.

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

Вывод здесь (работает на моем 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 голосов
/ 28 января 2012

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

...