mongodb - 百万数据aggregate group sum 统计超级耗时的问题,求解决方案
PHPz
PHPz 2017-05-02 09:20:16
0
3
1900

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以内能实现吗

PHPz
PHPz

学习是最好的投资!

membalas semua(3)
洪涛

Perkara pertama yang perlu diperhatikan ialah untuk operasi jenis OLAP, jangkaan tidak boleh terlalu tinggi. Lagipun, ia adalah operasi jumlah data yang besar sahaja jauh melebihi operasi OLTP biasa, jadi adalah tidak realistik dan tidak bermakna untuk memerlukan kelajuan dan keselarasan operasi OLTP. Tetapi itu tidak bermakna tiada ruang untuk pengoptimuman.
Mari mulakan dengan indeks. Berapa lamakah masa yang diambil untuk mencari 6 juta {user: "xiaoming"} item tanpa indeks? Imbasan jadual penuhCOLLSCANMencari 6 juta keping data daripada 7 juta keping data dan mencari 6 juta keping data daripada 100 juta keping data jelas merupakan dua konsep yang berbeza. Tekan indeks IXSCAN, perbezaan ini akan menjadi jauh lebih kecil dan hampir boleh diabaikan. Jadi anda salah untuk mengatakan {user: 1} bahawa indeks ini tidak mempunyai kesan. Ini mungkin hanya kerana jumlah data dalam koleksi terlalu kecil untuk melihat perbezaannya. Dengan cara ini, perlu disebutkan bahawa untuk melihat sama ada terdapat perbezaan dalam kecekapan, anda harus melihat rancangan pelaksanaan, bukan masa pelaksanaan, kerana masanya tidak tepat.
Dengan indeks user, masih terdapat 6 juta hasil, dan bahagian yang tinggal adalah regex tidak boleh mencapai indeks, jadi tidak bermakna sama ada terdapat indeks untuk regex atau tidak. Selepas menemui 6 juta keping data, terdapat satu lagi operasi info pada 6 juta keping data. Satu-satunya perkara yang boleh membantu untuk operasi ini ialah filter, tetapi pengindeksan teks penuh tidak boleh menggantikan sepenuhnya ungkapan biasa Anda perlu membaca dokumentasi untuk isu tertentu. Jika pengindeksan teks penuh boleh dilaksanakan, indeks komposit boleh diwujudkan: 全文索引

db.coll.createIndex({
  user: 1,
  info: "text"
});
Pertanyaan yang sepadan hendaklah ditukar kepada:

db.coll.aggregate([
  {$match:{user: 'xiaoming', $text: { $search: "wrong" }}},
  {$group:{_id:null, count:{$sum:1}}}
])
Untuk pengenalan kepada indeks teks penuh komposit, sila rujuk di sini Masih terdapat beberapa had yang perlu diambil perhatian. Selepas pengoptimuman ini, masa dijangka boleh dikurangkan kepada kurang daripada 20 saat di bawah perkakasan yang sama, yang masih jauh daripada 10 saat yang anda inginkan. Seperti yang dinyatakan pada mulanya, kami tidak boleh mempunyai jangkaan yang tinggi untuk OLAP. Jika anda benar-benar mempunyai keperluan ini, anda harus bermula dari sumber dan pertimbangkan:

  1. Kira setiap kali medan

    dikemas kini atau disisipkan info atau

  2. Buat statistik lengkap sekali-sekala, cache keputusan statistik dan paparkan terus kepada pengguna semasa pertanyaan

某草草

Saya tidak tahu, tetapi adakah lebih baik jika ia boleh dibahagikan kepada dua perlawanan? .

Serupa dengan

aggregate([
    {$match:{user: 'xiaoming'}},
    {$match:{info: /wrong/}},
    {$group:{_id:null, count:{$sum:1}}}
])

Perkara utama yang saya fikir adalah mengambil masa.
Jika ada indeks, indeks pengguna.

给我你的怀抱

Keperluan masa nyata tidak tinggi dan boleh dikira dengan kerap dan dicache

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan