Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sqlite vs File based data storing?

Tags:

ruby

Say I have a like class like so:

class User
  attr_accessor :name, :age
  def initialize(name, age)
    @name, @age = name, age
  end
end

Now, would it be faster to save the users as marshaled instances of the User class in individual files or to use an Sqlite database with an ORM? What are the disadvantages of a file based data store?

like image 392
RyanScottLewis Avatar asked Sep 27 '26 03:09

RyanScottLewis


2 Answers

Here are the results of a benchmark, performed on an SSD. Interpret them as you will. For very simple queries and data, marshalling and loading the entire dataset into memory appears faster:

Rehearsal ---------------------------------------------------------------
Storing in DB                 0.080000   0.000000   0.080000 (  0.085909)
Marshalling to Disk           0.010000   0.000000   0.010000 (  0.004340)
Fetching marshal              0.000000   0.000000   0.000000 (  0.002288)
Fetching records from DB      5.530000   0.130000   5.660000 (  5.657053)
Fetching records from Array   0.350000   0.000000   0.350000 (  0.347798)
Find one record from DB       0.320000   0.020000   0.340000 (  0.336068)
Find one record from Array    0.260000   0.000000   0.260000 (  0.258766)
------------------------------------------------------ total: 6.700000sec

                                  user     system      total        real
Storing in DB                 0.080000   0.000000   0.080000 (  0.079717)
Marshalling to Disk           0.000000   0.000000   0.000000 (  0.002595)
Fetching marshal              0.000000   0.000000   0.000000 (  0.001466)
Fetching records from DB     10.830000   0.230000  11.060000 ( 11.041669)
Fetching records from Array   0.340000   0.000000   0.340000 (  0.335473)
Find one record from DB       0.320000   0.010000   0.330000 (  0.336917)
Find one record from Array    0.260000   0.000000   0.260000 (  0.255746)

Here's the benchmark:

require 'benchmark'
require 'sequel'
class User
  attr_reader :name, :age
  def initialize(name, age)
    @name, @age = name, age
  end
  def to_hash; {name:@name, age:@age}; end
end
db_array = 1000.times.map{ User.new "name#{rand 1000}", rand(1000) }
db_array << User.new( "unique", 42 )
DBFILE  = 'users.db'; MARSHAL = 'users.marshal'
File.delete(DBFILE) if File.exists?(DBFILE)
DB = Sequel.sqlite(DBFILE)
DB.create_table(:users){ column(:name,:string); column(:age,:int) }
db_users = DB[:users]
Benchmark.bmbm do |x|
  x.report('Storing in DB'){ db_users.multi_insert db_array.map(&:to_hash) }
  x.report('Marshalling to Disk'){ File.open(MARSHAL, 'w'){ |f| f << Marshal.dump(db_array) } }
  x.report('Fetching marshal'){ db_array = Marshal.load(File.open(MARSHAL,'r'){|f| f.read }) }
  query = db_users.select{ name > "name500" }
  x.report('Fetching records from DB'){ 1000.times{ query.all } }
  x.report('Fetching records from Array'){ 1000.times{ db_array.select{ |u| u.name > "name500" } } }
  x.report('Find one record from DB'){ 1000.times{ db_users[name:'unique'] } }
  x.report('Find one record from Array'){ 1000.times{ db_array.find{ |u| u.name == "unique" } } }
end
like image 60
Phrogz Avatar answered Sep 28 '26 20:09

Phrogz


Storing marshalled objects has the disadvantage that your marshalled data will possibly not be compatible with future changes to the ruby class. So you would probably end up persisting basic structures like Hash or Array to the files. If you are at that point, using SQLite is the better option.

like image 22
moritz Avatar answered Sep 28 '26 21:09

moritz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!