Kann mir jemand helfen, diese Abfragen zu vergleichen und zu erklären, warum die PostgreSQL-Abfrage in knapp 2000 ms ausgeführt wird und die MongoDB-Gesamtabfrage fast 9000 ms und manchmal bis zu 130 KB dauert?
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-Abfrage
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-Abfrage
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}
}
])
Sowohl die PostgreSQL-Tabelle als auch die MongoDB-Auflistung sind auf datetime: 1 und locomotive_id: 1 indiziert
Diese Abfragen werden auf einem iMac mit einem 2-TB-Hybridlaufwerk und 16 GB Speicher getestet. Ich habe vergleichbare Ergebnisse auf einem Windows 7-Computer mit 8 GB Speicher und einer 256 GB SSD erhalten.
Vielen Dank!
** Update: Ich veröffentliche die EXPLAIN (BUFFERS, ANALYZE) Ergebnisse, nachdem meine Frage veröffentlicht wurde
"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"
** Update: Mongo erklären:
Erklären Sie aus MongoDB
{
"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
}
performance
mongodb
postgresql
Mike A.
quelle
quelle
EXPLAIN (BUFFERS, ANALYZE)
bitte Ausgabe anzeigen. Auch PostgreSQL-Version. (Ich habe dafür gestimmt, dies auf dba.SE zu verschieben){datetime: 1, prevdatetime: 1}
sollte eine bessere Leistung als der aktuelle Index erzielen, da Mongodb nach Datum und Uhrzeit filtert. Dies würde die Anzahl der zu scannenden Dokumente verringern.Antworten:
Alles, was PostgreSQL hier tut, ist ein Bitmap-Heap-Scan
bpkdmp_datetime_ix
, um Blöcke zu finden, die möglicherweise übereinstimmende Zeilen enthalten, und dann ein Heap-Scan dieser Blöcke, um übereinstimmende Zeilen zu findenbpkdmp
. Anschließend werden die Zeilen mithilfe von Hashes des Gruppierungsschlüssels in Hash-Buckets gruppiert, jeder Bucket summiert und die Ergebnisse sortiert. Es ist ein einfacher, grundlegender Abfrageplan - er funktioniert möglicherweise besser, wenn Sie viel darauf werfenwork_mem
, aber möglicherweise auch nicht.Auch in dieser Abfrage gibt es keine Parallelität. es wird alles auf einem Kern passieren.
Ich kann nur davon ausgehen, dass MongoDB eine weniger effiziente Methode verwendet oder nicht von einem geeigneten Index profitiert. Sie müssten die
explain
für die MongoDB-Abfrage anzeigen, damit dort ein nützlicher Kommentar möglich ist. siehecursor.explain
.quelle