¿Alguien puede ayudarme a comparar estas consultas y explicar por qué la consulta PostgreSQL se ejecuta en menos de 2000 ms y la consulta agregada MongoDB tarda casi 9000 ms y, a veces, hasta 130K ms?
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
Consulta PostgreSQL
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
Consulta MongoDB
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}
}
])
Tanto la tabla PostgreSQL como la colección MongoDB están indexadas en datetime: 1 y locomotive_id: 1
Estas consultas se están probando en un iMac con una unidad híbrida de 2 TB y 16 GB de memoria. He recibido resultados comparables en una máquina con Windows 7 con 8 GB de memoria y un SSD de 256 GB.
¡Gracias!
** Actualización: estoy publicando los resultados de EXPLAIN (BUFFERS, ANALYZE) después de que se publique mi pregunta
"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"
** Actualización: Mongo explica:
Explicar de 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
fuente
fuente

EXPLAIN (BUFFERS, ANALYZE)salida por favor. Además, la versión PostgreSQL. (He votado para mover esto a dba.SE){datetime: 1, prevdatetime: 1}debería funcionar mejor que el índice actual, ya que mongodb se filtra en datetime y prevdatetime. Disminuiría la cantidad de documentos que deben escanearse.Respuestas:
Todo lo que PostgreSQL está haciendo aquí es una exploración de montón de mapa de bits
bpkdmp_datetime_ixpara encontrar bloques que pueden contener filas coincidentes, luego una exploración de montón de esos bloques para encontrar filas coincidentesbpkdmp. Luego agrupa las filas en cubos hash utilizando los hashes de la clave de agrupación, suma cada cubo y clasifica los resultados. Es un plan de consulta simple y básico: podría funcionar mejor si le echas muchowork_mem, pero también podría no hacerlo.Tampoco hay paralelismo en ninguna parte de esa consulta; Todo sucederá en un núcleo.
Solo puedo suponer que MongoDB está utilizando un método menos eficiente o que no se beneficia de un índice apropiado. Tendría que mostrar la
explainconsulta MongoDB para que un comentario útil allí sea posible; vercursor.explain.fuente