mongodb 建立什么索引查询更快

2018-10-30 02:14:51 +08:00
 Ewig
{ "_id" : ObjectId("5bc4306ec3474d78e3780213"), "name" : "日本通货交换业协会-虚拟货币交易现状报告(日文)-2018.4.10-40 页.pdf", "unique_charcter" : "FiFhAChi7LSJxIq6IGdEjgHhiLPK" }
{ "_id" : ObjectId("5bc4306ec3474d78e3780214"), "name" : "秋叶大叔-给你一个社群你怎么管 v2-42 页.pdf", "unique_charcter" : "lnQuwPAAWDexZKnV1XbBjDRDNA71" }
{ "_id" : ObjectId("5bc4306ec3474d78e3780215"), "name" : "清科-清科观察:存托凭证本土化获官方认可,独家解读海外中企 CDR 模式回归 A 股路径-2018.4-13 页.pdf", "unique_charcter" : "FkWuGa1VKwZj9o4w06-2hiX-GCQL" }
{ "_id" : ObjectId("5bc4306ec3474d78e3780216"), "name" : "艾瑞-2018 年中国睡前音频收听场景研究报告-2018.3-38 页.pdf", "unique_charcter" : "FtU78sk1Emm50IRs89mQYYvc67lX" }
{ "_id" : ObjectId("5bc4306ec3474d78e3780217"), "name" : "德勤-2018 年全球生命科学发展趋势(英文)-2018-41 页.pdf", "unique_charcter" : "FjrR7vLkB6fjOONFB04hGq1pqsmm" }
{ "_id" : ObjectId("5bc4306ec3474d78e3780218"), "name" : "艾瑞-2018 年中国财经新媒体行业洞察报告-2018.3-48 页.pdf", "unique_charcter" : "FlXpGnt8-dTi6D5JQm9S0UsdSRYL" }
{ "_id" : ObjectId("5bc4306ec3474d78e3780219"), "name" : "艾瑞-2018 年中国共享充电宝行业研究报告-2018.3-44 页.pdf", "unique_charcter" : "Fiiab691SQI3U8LRNNP1nWPdeiCC" }

现在我是 name 和 unique_charcter 共同建立的键 如何使 find 查询更快?
self.xiaoMiQuanCollection.ensureIndex(key_word)
这样就可以吗?
4648 次点击
所在节点    MongoDB
13 条回复
Trim21
2018-10-30 02:36:26 +08:00
不知道你一般的查询条件是什么?
但是复合索引是同时通过 name 和 unique_charcter 查询才会通过索引,如果进行单键查询的话是不走索引的。
yuikns
2018-10-30 05:51:04 +08:00
想要确认是否的问题。可以使用 explain

db. xiaoMiQuanCollection.find({your_query_here}).explain()


这个会告诉你它 hit 了哪些 index

具体到此处,使用什么 index 作为 index value? 默认 1,长字符串可以考虑 hashed,要是保证是多字段一起查询,那么可以

db.xiaoMiQuanCollection.ensureIndex({name:'hashed', unique_charcter: 'hashed'})
Ewig
2018-10-30 11:15:02 +08:00
@yuikns mongodb 索引怎么还有唯一的区别,我的理解索引应该都是唯一的,否则还用索引干嘛?
Ewig
2018-10-30 11:19:10 +08:00
@yuikns TypeError: 'Collection' object is not callable. If you meant to call the 'createIndex' method on a 'Collection' object it is failing because no such method exists.

报错如上面的这是为啥,这是我写的创建索引的,我写 ensureindex 和 createIndex 都没有这个方法
index = self.xiaoMiQuanCollection.createIndex({"unique_charcter": 1, "name": 'hashed'}, {"unique": True})
res = self.xiaoMiQuanCollection.find(index)
yuikns
2018-10-30 11:35:06 +08:00
@Ewig huh? index and constraint are different concepts.

self 是啥? 为啥 create index 的结果会作为 query? 你是不是对 index 有什么误解啊

mongo 花费额外的开销和约束管理另外一套数据,内容是从 value 到 key set 的一个 dict。你 db.collection_name.getIndexes() 可以看到这个列表。所谓 unique, sparse 都是对那套数据结构的 constraints

你只要执行一次 build index 它就会永远保持,直到你显式删掉这个 index。
因此你


db.xiaoMiQuanCollection.createIndex({name:'hashed', unique_charcter: 'hashed'}, {unique: true})

一次后,就不用管它了。

然后直接 query 即可。

你这个错误是 pymongo 里面的,好好查文档嘛: https://api.mongodb.com/python/2.8/api/pymongo/collection.html?highlight=insert#pymongo.collection.Collection.create_index

>>> xiaoMiQuanCollection.create_index([("unique_charcter", pymongo.DESCENDING),
... ("name", pymongo.HASHED)], unique=True)

显然是这样嘛
yuikns
2018-10-30 11:38:03 +08:00
db.collection_name 是 mongo query, 不要和 python 的 api 混淆
Ewig
2018-10-30 11:54:06 +08:00
@yuikns xiaoMiQuanCollection.create_index([("unique_charcter", pymongo.DESCENDING),
... ("name", pymongo.HASHED)], unique=True)

你这个创建看,还有查找这个索引吧

index=xiaoMiQuanCollection.create_index([("unique_charcter", pymongo.DESCENDING),
... ("name", pymongo.HASHED)], unique=True)
然后查找 self.xiaoMiQuanCollection.find(index) 这样写?
Ewig
2018-10-30 11:57:03 +08:00
我在 python 里面 query 那个 index 方法没错吧
yuikns
2018-10-30 11:59:12 +08:00
Ewig
2018-10-30 12:16:38 +08:00
@yuikns index = self.xiaoMiQuanCollection.create_index([("unique_charcter", pymongo.DESCENDING), ("name", pymongo.HASHED)], unique=True)
res = self.xiaoMiQuanCollection.find(index)

我现在这样写,报错如下

pymongo.errors.OperationFailure: Currently only single field hashed index supported
JCZ2MkKb5S8ZX9pq
2018-10-30 17:08:09 +08:00
建索引和管理之类的我都是直接 GUI 里搞定的,一次性工作,用的 NoSQLBooster。
pymongo 就别折腾这些了,就做做查改删。
查询条件复杂特殊固定的话用复合的索引,但一般把用到的几个键单独索引也就够了。
Ewig
2018-10-30 19:02:07 +08:00
@JCZ2MkKb5S8ZX9pq
index = self.xiaomiquan_collection.create_index(
[("unique_charcter", pymongo.DESCENDING), ("name", 1)], unique=True)
res = self.xiaomiquan_collection.find(index)

我这个语法有问题吗?总是报错
JCZ2MkKb5S8ZX9pq
2018-10-31 16:53:23 +08:00
我觉得没有必要。
createIndex 做一次就够了,之后新录入 mongo 的数据,mongo 会自动索引,没必要每次都搞一下,做一次就永久有效,除非手动 drop。

我没有用 pymongo 这么做过,我不知道这儿 index 返回的是什么。
find 接受的是字典,你把 index 打出来看看是啥?不会是{name:1}吧?

最简单你建个 test collection,随便放个十万条 name 记录,先不做 index,搜索或者排序个一万次看看时间。
然后你 createIndex({name:1}),然后再对 name 搜索或排序一万次看看时间,还有 cpu 开销,就能感觉到差异了。

另外查看当前 index 的命令是 getIndexes,你那个 res 是不是想查看这个?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/502380

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX