假设我有一个类似的课程,如下所示:
class User
attr_accessor :name, :age
def initialize(name, age)
@name, @age = name, age
end
end
Run Code Online (Sandbox Code Playgroud)
现在,将用户保存为单个文件中 User 类的编组实例或者使用带有 ORM 的 Sqlite 数据库会更快吗?基于文件的数据存储有哪些缺点?
以下是在 SSD 上执行的基准测试结果。按照您的意愿解释它们。对于非常简单的查询和数据,将整个数据集编组并加载到内存中显得更快:
\n\n\n\nRehearsal ---------------------------------------------------------------\nStoring in DB \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.080000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.080000 ( \xc2\xa00.085909)\nMarshalling to Disk \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.010000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.010000 ( \xc2\xa00.004340)\nFetching marshal \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.000000 ( \xc2\xa00.002288)\nFetching records from DB \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa05.530000 \xc2\xa0\xc2\xa00.130000 \xc2\xa0\xc2\xa05.660000 ( \xc2\xa05.657053)\nFetching records from Array \xc2\xa0\xc2\xa00.350000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.350000 ( \xc2\xa00.347798)\nFind one record from DB \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.320000 \xc2\xa0\xc2\xa00.020000 \xc2\xa0\xc2\xa00.340000 ( \xc2\xa00.336068)\nFind one record from Array \xc2\xa0\xc2\xa0\xc2\xa00.260000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.260000 ( \xc2\xa00.258766)\n------------------------------------------------------ total: 6.700000sec\n\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0user \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0system \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0total \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0real\nStoring in DB \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.080000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.080000 ( \xc2\xa00.079717)\nMarshalling to Disk \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.000000 ( \xc2\xa00.002595)\nFetching marshal \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.000000 ( \xc2\xa00.001466)\nFetching records from DB \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa010.830000 \xc2\xa0\xc2\xa00.230000 \xc2\xa011.060000 ( 11.041669)\nFetching records from Array \xc2\xa0\xc2\xa00.340000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.340000 ( \xc2\xa00.335473)\nFind one record from DB \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa00.320000 \xc2\xa0\xc2\xa00.010000 \xc2\xa0\xc2\xa00.330000 ( \xc2\xa00.336917)\nFind one record from Array \xc2\xa0\xc2\xa0\xc2\xa00.260000 \xc2\xa0\xc2\xa00.000000 \xc2\xa0\xc2\xa00.260000 ( \xc2\xa00.255746)\nRun Code Online (Sandbox Code Playgroud)\n\n这是基准:
\n\n\n\nrequire \'benchmark\'\nrequire \'sequel\'\nclass User\n attr_reader :name, :age\n def initialize(name, age)\n @name, @age = name, age\n end\n def to_hash; {name:@name, age:@age}; end\nend\ndb_array = 1000.times.map{ User.new "name#{rand 1000}", rand(1000) }\ndb_array << User.new( "unique", 42 )\nDBFILE = \'users.db\'; MARSHAL = \'users.marshal\'\nFile.delete(DBFILE) if File.exists?(DBFILE)\nDB = Sequel.sqlite(DBFILE)\nDB.create_table(:users){ column(:name,:string); column(:age,:int) }\ndb_users = DB[:users]\nBenchmark.bmbm do |x|\n x.report(\'Storing in DB\'){ db_users.multi_insert db_array.map(&:to_hash) }\n x.report(\'Marshalling to Disk\'){ File.open(MARSHAL, \'w\'){ |f| f << Marshal.dump(db_array) } }\n x.report(\'Fetching marshal\'){ db_array = Marshal.load(File.open(MARSHAL,\'r\'){|f| f.read }) }\n query = db_users.select{ name > "name500" }\n x.report(\'Fetching records from DB\'){ 1000.times{ query.all } }\n x.report(\'Fetching records from Array\'){ 1000.times{ db_array.select{ |u| u.name > "name500" } } }\n x.report(\'Find one record from DB\'){ 1000.times{ db_users[name:\'unique\'] } }\n x.report(\'Find one record from Array\'){ 1000.times{ db_array.find{ |u| u.name == "unique" } } }\nend\nRun Code Online (Sandbox Code Playgroud)\n