Created
May 21, 2011 04:03
-
-
Save ahoward/984235 to your computer and use it in GitHub Desktop.
mongo-should-be-bloody-faster.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# following is a little benchmark looking a real world example of inserting a | |
# bunch of records into pg and mongo using a few methods available in ruby. | |
# this is not meant to be an apples to apples benchmark, rather it's trying to | |
# see how the various dbs might perform in a real world situation. i know | |
# mongo does not fsync to disk. i know it's not fair using a transaction with | |
# the rdbms, but these conditions will exist in real world usage and it's that | |
# which i'm interested in. | |
# | |
# here is a few runs | |
# | |
# n = 10_000 (with transactions) | |
# | |
# user system total real | |
# pg 0.840000 0.330000 1.170000 ( 3.265902) | |
# sequel 6.350000 0.540000 6.890000 ( 10.261432) | |
# ar model 11.860000 0.380000 12.240000 ( 15.038289) | |
# mongid model 9.400000 0.520000 9.920000 ( 35.926766) | |
# mongo 5.920000 0.410000 6.330000 ( 7.749044) | |
# | |
# | |
# n = 10_000 (*without* transactions - code was modified) | |
# | |
# user system total real | |
# pg 0.900000 0.440000 1.350000 ( 7.976228) | |
# sequel 6.150000 0.560000 6.710000 ( 13.553662) | |
# ar model 11.500000 0.790000 12.290000 ( 18.490117) | |
# mongid model 9.330000 0.530000 9.860000 ( 35.956647) | |
# mongo 5.710000 0.410000 6.120000 ( 7.577185) | |
# | |
# | |
# n = 100_000 (with transactions) | |
# | |
# user system total real | |
# pg 8.450000 2.780000 11.230000 ( 37.551105) | |
# sequel 69.880000 5.170000 75.050000 (103.346337) | |
# ar model233.250000 3.860000 237.110000 (265.600197) | |
# mongid model145.180000 5.910000 151.090000 (2443.426801) | |
# mongo 51.490000 3.920000 55.410000 ( 70.370120) | |
# | |
# | |
# | |
# summary of results: | |
# | |
# 1) raw pg is almost as fast(er) as raw mongo and a *lot* more durable. | |
# 2) ar has gotten much, much better. | |
# | |
# | |
## setup | |
# | |
require 'rubygems' | |
require 'ostruct' | |
require 'benchmark' | |
require 'uuidtools' | |
require 'active_record' | |
require 'mongoid' | |
## cli options | |
# | |
STDOUT.sync = true | |
$n = (ARGV.shift || 1000).to_i | |
## config | |
# | |
C = | |
OpenStruct.new( | |
'db' => (ENV['USER'] || 'bench'), | |
'table' => 'bench' | |
) | |
## setup a sequel connection | |
# | |
require 'sequel' | |
S = Sequel.connect("postgres://localhost/#{ C.db }") | |
require 'sequel_pg' | |
## setup an ar class | |
# | |
ActiveRecord::Base.establish_connection(:adapter => 'postgresql', :database => C.db) | |
class A < ActiveRecord::Base | |
set_table_name C.table | |
end | |
## setup mongoid class | |
# | |
Mongoid.configure do |config| | |
config.master = Mongo::Connection.new.db(C.db) | |
end | |
class M | |
include Mongoid::Document | |
self.collection_name = C.table | |
field(:value) | |
index(:value, :unique => true) | |
end | |
A.delete_all | |
## make sure the rdbms table is setup and indexed | |
# | |
S.drop_table(C.table) if S.table_exists?(C.table) | |
S.create_table(C.table) do | |
primary_key(:id) | |
String(:value, :unique => true, :null => false) | |
end | |
## make sure the mongo collection is setup and indexed | |
# | |
M.delete_all | |
M.create_indexes | |
## bench | |
# | |
def values() Array.new($n).map{ UUIDTools::UUID.timestamp_create.to_s } end | |
Benchmark.bm do |bm| | |
sequel = S[:bench] | |
mongo = M.collection.db.collection(C.table) | |
pg = A.connection.raw_connection | |
bm.report 'pg' do | |
pg.exec('begin transaction') | |
values.each do |value| | |
res = pg.exec('insert into bench values(default, $1) returning id', [value]) | |
id = res.getvalue(0,0) | |
res = pg.exec('select * from bench where id=$1', [id]) | |
end | |
pg.exec('commit') | |
end | |
bm.report 'sequel' do | |
S.transaction do | |
values.each do |value| | |
id = sequel.insert(:value => value) | |
sequel.where(:id => id).first | |
end | |
end | |
end | |
bm.report 'ar model' do | |
A.transaction do | |
values.each do |value| | |
r = A.create!(:value => value) | |
A.where(:id => r.id).first | |
end | |
end | |
end | |
bm.report 'mongid model' do | |
values.each do |value| | |
r = M.safely.create!(:value => value) | |
M.where(:id => r.id).first | |
end | |
end | |
bm.report 'mongo' do | |
values.each do |value| | |
id = mongo.insert({:value => value}, {:safe => true}) | |
mongo.find(:_id => id).first | |
end | |
end | |
end |
paul
commented
May 21, 2011
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment