简体   繁体   中英

Is a mongodb query with 1 indexed field faster than multiple indexed fields?

In the following model a product is owned by a customer. and cannot be ordered by other customers. So I know that in an order by customer 1 there can only be products owned by customer one.

To give you an idea here is a simple version of the data model:

Orders:

{
  'customer' : 1
  'products' : [
  {'productId' : 'a'},
  {'productId' : 'b'}
  ]
}

Products:

{
  'id' : 'a'
  'name' : 'somename'
  'customer' : 1 
}

I need to find orders that contain certain products. I know the product id and customer id. I'm free to add/change indexes on my database.

Now my question is. Is it faster to just add a single field index on the product id's and query only using that ID. Or should I go for a compound index with customer and product id?

I'm not sure if this matters, but in my real model the list of products is actually a list of objects which have an amount and a dbref to the product. And the customer is also a dbref.

Here is a full order object:

{
    "_id" : 0,
    "_class" : "nl.pfa.myprintforce.models.Order",
    "orderNumber" : "e35f1fa8-b4c4-4d53-89c9-66abe94a3553",
    "status" : "ERROR",
    "created" : ISODate("2017-03-30T11:50:50.292Z"),
    "finished" : false,
    "orderTime" : ISODate("2017-01-12T12:50:50.292Z"),
    "expectedDelivery" : ISODate("2017-03-30T11:50:50.292Z"),
    "totalItems" : 19,
    "orderItems" : [ 
        {
            "amount" : 4,
            "product" : {
                "$ref" : "product",
                "$id" : NumberLong(16)
            }
        }, 
        {
            "amount" : 7,
            "product" : {
                "$ref" : "product",
                "$id" : NumberLong(26)
            }
        }, 
        {
            "amount" : 8,
            "product" : {
                "$ref" : "product",
                "$id" : NumberLong(7)
            }
        }
    ],
    "stateList" : [ 
        {
            "timestamp" : ISODate("2017-03-28T11:50:50.074Z"),
            "status" : "NEW",
            "message" : ""
        }, 
        {
            "timestamp" : ISODate("2017-03-29T11:50:50.075Z"),
            "status" : "IN_PRODUCTION",
            "message" : ""
        }, 
        {
            "timestamp" : ISODate("2017-03-30T11:50:50.075Z"),
            "status" : "ERROR",
            "message" : "Something went wrong"
        }
    ],
    "customer" : {
        "$ref" : "customer",
        "$id" : ObjectId("58dcf11a71571a24c475c044")
    }
}

When I have the following indexes:

1: {"customer" : 1, "orderItems.product" : 1}
2: {"orderItems.product" : 1}

both count queries (I use count to forcefully find all documents without the network transfer):

a: db.getCollection('order').find({
'orderItems.product' : DBRef('product',113)
}).count()

b: db.getCollection('order').find({
'customer' : DBRef('customer',ObjectId("58de009671571a07540a51d5")),
'orderItems.product' : DBRef('product',113)
}).count()

Run with the same time of ~0.007 seconds on a set of 200k. When I add 1000k record for a different customer (and different products) it does not effect the time at all.

an extended explain shows that:

query 1 just uses index 2. query 2 uses index 2 but also considered index 1. Perhaps index intersection is used here?

Because if I drop index 1 the results are:

Query a: 0.007 seconds Query b: 0.035 seconds (5x as long!)

So my conclusion is that with the right indexing both methods work about as fast. However, if you do not need the compound index for anything else it's just a waste of space & write speed.

So: in my case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM