1、文档结构示例
{
_id: xxxx,
user: 'xiaoming',
level: 5,
from: 'iPhone',
info: 'something wrong'
}
2、场景:user为'xiaoming'的文档有六七百万条
3、问题:怎么提升aggregate+group+sum速度
aggregate([
{$match:{user: 'xiaoming', info:{$regex:'wrong'}}},
{$group:{_id:null, count:{$sum:1}}}
])
用上面这个来统计xiaoming带有wrong的文档数量,结果
{"_id": null, "count": 2299999 }
耗时30s-40s。user、info、user+info三种索引都尝试过,速度都没有提升
baidu、google查到‘带条件计数慢无解’
怎么提升效率,10s以内能实现吗
PHP中文网2017-05-02 09:22:16
最初に説明することは、OLAP タイプの操作では期待値が高すぎてはいけないということです。結局のところ、IO だけで通常の OLTP 操作をはるかに超える大量のデータの操作であるため、OLTP 操作の速度と同時実行性を要求することは非現実的であり、意味がありません。しかし、それは最適化の余地がないという意味ではありません。
まずはインデックスから始めましょう。インデックスを作成せずに 600 万の {user: "xiaoming"}
を見つけるのにどれくらい時間がかかりますか?フルテーブルスキャン COLLSCAN
で 700 万個のデータから 600 万個のデータを見つけることと、1 億個のデータから 600 万個のデータを見つけることは、明らかに 2 つの異なる概念です。インデックス IXSCAN
がヒットした場合、その差ははるかに小さくなり、ほとんど無視できます。したがって、 {user: 1}
インデックスが効果がないというのは間違いです。コレクション内のデータ量が少なすぎて違いが分からないだけかもしれません。ちなみに、時間は不正確であるため、効率に違いがあるかどうかを確認するには、実行時間ではなく実行計画を見る必要があることに注意してください。 {user: "xiaoming"}
需要多少时间?全表扫描COLLSCAN
从700w条数据中找出600w条,跟从1亿条数据中找出600w条显然是两个概念。命中索引IXSCAN
,这个差异就会小很多,几乎可以忽略。所以你说{user: 1}
这个索引没有作用是不对的,可能只是因为集合数据量太少看不出差异而已。顺便应该提一下看效率是否有差异应该看执行计划,不要看执行时间,时间是不准确的。
在有user
索引的前提下,结果仍然有600w条,剩下的部分是个regex
,regex
无法命中索引,所以不管有没有对info
的索引都没有意义。在找到600w条数据之后还有一个对600w数据的filter
操作。唯一对这个操作可能有帮助的只有全文索引
,但全文索引并不能完全替代正则,具体问题需要读一下文档。考虑全文索引可行的情况下,可以建立复合索引:
db.coll.createIndex({
user: 1,
info: "text"
});
对应地查询应该改为:
db.coll.aggregate([
{$match:{user: 'xiaoming', $text: { $search: "wrong" }}},
{$group:{_id:null, count:{$sum:1}}}
])
关于复合全文索引的介绍参考这里,仍然是有些限制需要注意。这样优化之后预计在同样的硬件下能降到20s以内,跟你要的10s内还有一段距离。原因开头说了,对OLAP就不能期望这么高。如果你真有这方面的需求,就应该从源头入手,考虑:
每次info
user
インデックスの前提では、まだ 600 万件の結果があり、残りの部分は regex
がインデックスにヒットできません。 info
へのインデックスがあるかどうかは関係ありません。 600 万個のデータが見つかった後、600 万個のデータに対して filter
操作が行われます。この操作に役立つ唯一のものは フルテキスト インデックス
ですが、フルテキスト インデックスは正規表現を完全に置き換えることはできません。特定の質問についてはドキュメントを読む必要があります。全文インデックス作成が可能であることを考慮すると、複合インデックスを確立できます:
リーリー
<オル>
info
フィールドが更新または挿入されるたびにカウントします某草草2017-05-02 09:22:16
分かりませんが、2試合に分けた方が良いでしょうか? 。
に似ている リーリー
大切なのは規則的に時間を過ごすことだと思います。インデックスがある場合は、ユーザーをインデックスします。