Hiệu suất MongoDB so với PostgreSQL với 5,5 triệu hàng / tài liệu


10

Ai đó có thể giúp tôi so sánh các truy vấn này và giải thích lý do tại sao truy vấn PostgreSQL thực hiện chỉ trong vòng dưới 2000ms và truy vấn tổng hợp MongoDB mất gần 9000ms và đôi khi cao tới 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

Truy vấn 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

Truy vấn 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}
   }
])

Cả bảng PostgreSQL và bộ sưu tập MongoDB đều được lập chỉ mục trên datetime: 1 và locomactor_id: 1

Các truy vấn này đang được thử nghiệm trên iMac với ổ đĩa lai 2TB và bộ nhớ 16GB. Tôi đã nhận được kết quả tương đương trên máy Windows 7 với bộ nhớ 8GB và ổ SSD 256 GB.

Cảm ơn!

** Cập nhật: Tôi đang đăng kết quả GIẢI THÍCH (BUFFERS, ANALYZE) sau khi câu hỏi của tôi được đăng

"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"

** Cập nhật: Mongo giải thích:

Giải thích từ 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
}

1
Đối với EXPLAIN (BUFFERS, ANALYZE)đầu ra hiển thị truy vấn PostgreSQL xin vui lòng. Ngoài ra, phiên bản PostgreSQL. (Tôi đã bỏ phiếu để chuyển cái này sang dba.SE)
Craig Ringer

... và thông tin về kế hoạch MongoDB? docs.mongodb.org/manual/reference/method/coder.explain
Craig Ringer

2
Mặc dù khó có thể thoát khỏi sự cường điệu của NoQuery, nhưng RDBMS truyền thống tốt hơn và trưởng thành hơn rất nhiều trong các tổng hợp bất kỳ ngày nào. Các cơ sở dữ liệu NoQuery được tối ưu hóa cho việc lập chỉ mục và truy xuất khóa chính bằng khóa chứ không phải cho các loại truy vấn đó.
Alexandros

Tôi có thể đã bỏ qua một chi tiết nhỏ. Có hơn 200 lĩnh vực trong mỗi tài liệu. Đây là một nhập trực tiếp từ cơ sở dữ liệu PostgreQuery. Rất nhiều giá trị trường là null. Tôi nhớ lại MongoDB không đặc biệt thích các giá trị null. Tôi đã thực hiện một lần nhập khác với <20 trường dữ liệu có liên quan và hiệu suất truy vấn tốt hơn. Tôi nhận được <3000ms trên máy có bộ nhớ 8GB và HD chậm hơn. Tôi sẽ sớm bắt đầu một thử nghiệm mới trên một cỗ máy mạnh hơn nhiều.
Mike A

Chỉ mục Mongodb {datetime: 1, prevdatetime: 1}sẽ hoạt động tốt hơn chỉ mục hiện tại, vì các bộ lọc mongodb trên datetime và prevdatetime. Nó sẽ làm giảm số lượng tài liệu cần được quét.
rubish

Câu trả lời:


8

Tất cả PostgreSQL đang làm ở đây là quét heap bitmap bpkdmp_datetime_ixđể tìm các khối có thể chứa các hàng khớp, sau đó quét heap các khối đó để tìm các hàng khớp bpkdmp. Sau đó, nhóm các hàng thành các nhóm băm bằng cách sử dụng băm của khóa nhóm, tính tổng từng nhóm và sắp xếp kết quả. Đó là một kế hoạch truy vấn cơ bản, đơn giản - nó có thể hoạt động tốt hơn nếu bạn ném nhiều work_memvào nó, nhưng nó cũng có thể không.

Không có sự song song ở bất cứ đâu trong truy vấn đó; tất cả sẽ xảy ra trên một lõi.

Tôi chỉ có thể giả định rằng MongoDB đang sử dụng một phương pháp kém hiệu quả hơn hoặc không được hưởng lợi từ một chỉ mục thích hợp. Bạn cần hiển thị explaintruy vấn MongoDB để có thể nhận xét hữu ích; thấy cursor.explain.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.