5.5 milyon satır / belge ile MongoDB performansı ve PostgreSQL


10

Birisi bu sorguları karşılaştırmama ve PostgreSQL sorgusunun neden 2000ms'in hemen altında yürütüldüğünü ve MongoDB toplam sorgusunun neredeyse 9000ms ve bazen 130K ms kadar yüksek olduğunu açıklamama yardımcı olabilir mi?

PostgreSQL 9.3.2 on x86_64-apple-darwin, compiled by i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.9.00), 64-bit

PostgreSQL sorgusu

SELECT locomotive_id,
   SUM(date_trunc('second', datetime) - date_trunc('second', prevDatetime)) AS utilization_time

FROM bpkdmp 
WHERE datetime >= '2013-7-26 00:00:00.0000' 
AND   datetime <= '2013-7-26 23:59:59.9999'
GROUP BY locomotive_id
order by locomotive_id

MongoDB Sorgusu

db.bpkdmp.aggregate([
   {
      $match : {
          datetime : { $gte : new Date(2013,6,26, 0, 0, 0, 0), $lt : new Date(2013,6,26, 23, 59, 59, 9999) }
   }
   },
   {
      $project: {
         locomotive_id : "$locomotive_id",
         loco_time : { $subtract : ["$datetime", "$prevdatetime"] }, 
      }
   },
   {
      $group : {
         _id : "$locomotive_id",
         utilization_time : { $sum : "$loco_time" }
      }
   },
   {
      $sort : {_id : 1}
   }
])

Hem PostgreSQL tablosu hem de MongoDB koleksiyonu datetime: 1 ve locomotive_id: 1 dizinlerinde dizine eklenir

Bu sorgular, 2 TB'lık bir hibrit sürücüye ve 16 GB belleğe sahip bir iMac üzerinde test ediliyor. 8GB belleğe ve 256GB SSD'ye sahip bir Windows 7 makinesinde karşılaştırılabilir sonuçlar aldım.

Teşekkürler!

** Güncelleme: Sorum gönderildikten sonra EXPLAIN (BUFFERS, ANALYZE) sonuçlarını gönderiyorum

"Sort  (cost=146036.84..146036.88 rows=19 width=24) (actual time=2182.443..2182.457 rows=152 loops=1)"
"  Sort Key: locomotive_id"
"  Sort Method: quicksort  Memory: 36kB"
"  Buffers: shared hit=13095"
"  ->  HashAggregate  (cost=146036.24..146036.43 rows=19 width=24) (actual time=2182.144..2182.360 rows=152 loops=1)"
"        Buffers: shared hit=13095"
"        ->  Bitmap Heap Scan on bpkdmp  (cost=12393.84..138736.97 rows=583942 width=24) (actual time=130.409..241.087 rows=559529 loops=1)"
"              Recheck Cond: ((datetime >= '2013-07-26 00:00:00'::timestamp without time zone) AND (datetime <= '2013-07-26 23:59:59.9999'::timestamp without time zone))"
"              Buffers: shared hit=13095"
"              ->  Bitmap Index Scan on bpkdmp_datetime_ix  (cost=0.00..12247.85 rows=583942 width=0) (actual time=127.707..127.707 rows=559529 loops=1)"
"                    Index Cond: ((datetime >= '2013-07-26 00:00:00'::timestamp without time zone) AND (datetime <= '2013-07-26 23:59:59.9999'::timestamp without time zone))"
"                    Buffers: shared hit=1531"
"Total runtime: 2182.620 ms"

** Güncelleme: Mongo açıklıyor:

MongoDB'den açıkla

{
"serverPipeline" : [
    {
        "query" : {
            "datetime" : {
                "$gte" : ISODate("2013-07-26T04:00:00Z"),
                "$lt" : ISODate("2013-07-27T04:00:08.999Z")
            }
        },
        "projection" : {
            "datetime" : 1,
            "locomotive_id" : 1,
            "prevdatetime" : 1,
            "_id" : 1
        },
        "cursor" : {
            "cursor" : "BtreeCursor datetime_1",
            "isMultiKey" : false,
            "n" : 559572,
            "nscannedObjects" : 559572,
            "nscanned" : 559572,
            "nscannedObjectsAllPlans" : 559572,
            "nscannedAllPlans" : 559572,
            "scanAndOrder" : false,
            "indexOnly" : false,
            "nYields" : 1,
            "nChunkSkips" : 0,
            "millis" : 988,
            "indexBounds" : {
                "datetime" : [
                    [
                        ISODate("2013-07-26T04:00:00Z"),
                        ISODate("2013-07-27T04:00:08.999Z")
                    ]
                ]
            },
            "allPlans" : [
                {
                    "cursor" : "BtreeCursor datetime_1",
                    "n" : 559572,
                    "nscannedObjects" : 559572,
                    "nscanned" : 559572,
                    "indexBounds" : {
                        "datetime" : [
                            [
                                ISODate("2013-07-26T04:00:00Z"),
                                ISODate("2013-07-27T04:00:08.999Z")
                            ]
                        ]
                    }
                }
            ],
            "oldPlan" : {
                "cursor" : "BtreeCursor datetime_1",
                "indexBounds" : {
                    "datetime" : [
                        [
                            ISODate("2013-07-26T04:00:00Z"),
                            ISODate("2013-07-27T04:00:08.999Z")
                        ]
                    ]
                }
            },
            "server" : "Michaels-iMac.local:27017"
        }
    },
    {
        "$project" : {
            "locomotive_id" : "$locomotive_id",
            "loco_time" : {
                "$subtract" : [
                    "$datetime",
                    "$prevdatetime"
                ]
            }
        }
    },
    {
        "$group" : {
            "_id" : "$locomotive_id",
            "utilization_time" : {
                "$sum" : "$loco_time"
            }
        }
    },
    {
        "$sort" : {
            "sortKey" : {
                "_id" : 1
            }
        }
    }
],
"ok" : 1
}

1
PostgreSQL sorgu göster EXPLAIN (BUFFERS, ANALYZE)çıkış için lütfen. Ayrıca, PostgreSQL sürümü. (Bunu dba.SE'ye taşımak için oy verdim)
Craig Ringer


2
NoSQL yutturmacadan kaçmak zor olsa da, geleneksel RDBMS daha iyi ve her gün agregalarda çok daha olgun. NoSQL veritabanları, bu tür sorgular için değil, birincil anahtar dizine ekleme ve anahtarla alma için optimize edilmiştir.
Alexandros

Küçük bir ayrıntı bırakmış olabilirim. Her belgede 200'den fazla alan vardır. Bu, bir PostgreSQL veritabanından doğrudan içe aktarılmıştı. Alan değerlerinin çoğu boş. MongoDB'nin null değerlere özellikle düşkün olmadığını hatırladım. İlgili veri <20 alan ile başka bir ithalat yaptım ve sorgu performansı büyüklükleri daha iyi. 8 GB belleğe ve daha yavaş HD'ye sahip bir makinede 3000 ms'den az alıyorum. Kısa süre içinde çok daha güçlü bir makinede yeni bir teste başlayacağım.
Mike A

Mongodb dizini {datetime: 1, prevdatetime: 1}, tarih ve prevdatetime üzerindeki mongodb filtreleri olduğundan, geçerli dizinden daha iyi performans göstermelidir. Taranması gereken belge sayısını azaltacaktır.
rubish

Yanıtlar:


8

Burada yapılan tüm PostgreSQL, bpkdmp_datetime_ixeşleşen satırları içerebilecek blokları bulmak için bir bitmap yığın taraması , ardından eşleşen satırları bulmak için bu blokların bir yığın taramasıdır bpkdmp. Daha sonra, gruplandırma anahtarının karma değerlerini kullanarak satırları karma kovalar halinde gruplandırır, her bir grubu toplar ve sonuçları sıralar. Bu basit, temel bir sorgu planıdır - çok fazla atarsanız daha iyi performans gösterebilir work_mem, ancak bu da olmayabilir.

Bu sorguda hiçbir yerde paralellik yoktur; hepsi tek bir çekirdek üzerinde olacak.

Yalnızca MongoDB'nin daha az verimli bir yöntem kullandığını veya uygun bir dizinden faydalanmadığını varsayabilirim. explainMümkün olan faydalı bir yorum için MongoDB sorgusunu göstermeniz gerekir ; bakın cursor.explain.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.