我收集了 500 万个具有正确索引的文档。$ 工作完美,但相同的查询 $nin 超级慢......这是什么原因?
超快:
{'tech': {'$in': ['Wordpress', 'wordpress', 'WORDPRESS']}}
超级慢..
{'tech': {'$nin': ['Wordpress', 'wordpress', 'WORDPRESS']}}
Mongo v3.2 进行了各种存储引擎更改,提高了在此问题上的性能。
现在
$nin
哈希一个重要的品质,这不是一个选择性查询吗,首先让我们了解一下选择性意味着什么:
选择性是查询使用索引缩小结果范围的能力。有效索引更具选择性,允许 MongoDB 使用索引来完成与完成查询相关的大部分工作。
现在他们甚至自己声明:
例如,不等运算符 $nin 和 $ne 的选择性不是很强,因为它们通常匹配索引的很大一部分。因此,在许多情况下,带有索引的 $nin 或 $ne 查询的性能可能并不比必须扫描集合中所有文档的 $nin 或 $ne 查询好。
当时
selectivity
对于性能来说是一件大事。这一切都引出了您的问题,为什么不使用索引?
当 Mongo 被要求创建一个查询计划时,他会在所有可用查询计划之间进行“竞赛”,其中一个是
COLSCAN
,即集合扫描,第一个找到 101 个文档的计划获胜。由于非选择性查询的效率很低,获胜计划(实际上通常更快,具体取决于查询中的索引和值)是COLSCAN
,请在here进一步了解这一点
当你有索引时(无论你谈论 MongoDB 还是任何其他数据库),搜索某个值总是比搜索不存在的值更快。
数据库必须扫描整个索引,当您查找“not in”或“not equal”时,通常甚至不使用索引。使用
explain()
查看执行计划
一些数据库(例如 Oracle)提供所谓的位图索引。它们的工作方式不同,通常
IN
操作与 NOT IN
操作一样快。但是,与往常一样,与 B*Tree 索引相比,它们还有其他缺点。据我所知,Oracle 数据库是唯一支持位图索引的主要 RDBMS。
如果 $nin 或 $ne 仅包含一个值,为什么他们需要扫描记录。
例如: 用户 |已付 1 |是 2 | N
如果我问 ispayed != 'Y',他们仍然可以扫描索引并做出决定,对吗?