mini_sql 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +1 -1
- data/CHANGELOG +4 -0
- data/README.md +36 -0
- data/bench/builder_perf.rb +138 -0
- data/bench/decorator_perf.rb +143 -0
- data/bench/mini_sql_methods_perf.rb +80 -0
- data/bench/prepared_perf.rb +59 -0
- data/bench/shared/generate_data.rb +133 -0
- data/bench/topic_perf.rb +21 -327
- data/bench/topic_wide_perf.rb +92 -0
- data/lib/mini_sql.rb +17 -8
- data/lib/mini_sql/abstract/prepared_binds.rb +74 -0
- data/lib/mini_sql/abstract/prepared_cache.rb +45 -0
- data/lib/mini_sql/builder.rb +61 -30
- data/lib/mini_sql/inline_param_encoder.rb +4 -3
- data/lib/mini_sql/mysql/connection.rb +6 -0
- data/lib/mini_sql/mysql/deserializer_cache.rb +3 -3
- data/lib/mini_sql/mysql/prepared_binds.rb +15 -0
- data/lib/mini_sql/mysql/prepared_cache.rb +21 -0
- data/lib/mini_sql/mysql/prepared_connection.rb +44 -0
- data/lib/mini_sql/postgres/connection.rb +6 -0
- data/lib/mini_sql/postgres/deserializer_cache.rb +5 -5
- data/lib/mini_sql/postgres/prepared_binds.rb +15 -0
- data/lib/mini_sql/postgres/prepared_cache.rb +25 -0
- data/lib/mini_sql/postgres/prepared_connection.rb +36 -0
- data/lib/mini_sql/postgres_jdbc/deserializer_cache.rb +3 -3
- data/lib/mini_sql/result.rb +10 -0
- data/lib/mini_sql/serializer.rb +29 -15
- data/lib/mini_sql/sqlite/connection.rb +9 -1
- data/lib/mini_sql/sqlite/deserializer_cache.rb +3 -3
- data/lib/mini_sql/sqlite/prepared_binds.rb +15 -0
- data/lib/mini_sql/sqlite/prepared_cache.rb +21 -0
- data/lib/mini_sql/sqlite/prepared_connection.rb +40 -0
- data/lib/mini_sql/version.rb +1 -1
- metadata +19 -2
@@ -0,0 +1,133 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class GenerateData
|
4
|
+
class ::Topic < ActiveRecord::Base;
|
5
|
+
belongs_to :user
|
6
|
+
belongs_to :category
|
7
|
+
end
|
8
|
+
class ::User < ActiveRecord::Base; end
|
9
|
+
class ::Category < ActiveRecord::Base; end
|
10
|
+
|
11
|
+
def initialize(count_records:)
|
12
|
+
@count_records = count_records
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
conn_settings = {
|
17
|
+
password: 'postgres',
|
18
|
+
user: 'postgres',
|
19
|
+
host: 'localhost'
|
20
|
+
}
|
21
|
+
|
22
|
+
db_conn = conn_settings.merge(database: "test_db", adapter: "postgresql")
|
23
|
+
|
24
|
+
pg = PG::Connection.new(conn_settings)
|
25
|
+
pg.exec "DROP DATABASE IF EXISTS test_db"
|
26
|
+
pg.exec "CREATE DATABASE test_db"
|
27
|
+
pg.close
|
28
|
+
|
29
|
+
ActiveRecord::Base.establish_connection(db_conn)
|
30
|
+
pg = ActiveRecord::Base.connection.raw_connection
|
31
|
+
|
32
|
+
pg.exec <<~SQL
|
33
|
+
drop table if exists topics;
|
34
|
+
drop table if exists users;
|
35
|
+
drop table if exists categories;
|
36
|
+
CREATE TABLE topics (
|
37
|
+
id integer NOT NULL PRIMARY KEY,
|
38
|
+
title character varying NOT NULL,
|
39
|
+
last_posted_at timestamp without time zone,
|
40
|
+
created_at timestamp without time zone NOT NULL,
|
41
|
+
updated_at timestamp without time zone NOT NULL,
|
42
|
+
views integer DEFAULT 0 NOT NULL,
|
43
|
+
posts_count integer DEFAULT 0 NOT NULL,
|
44
|
+
user_id integer,
|
45
|
+
last_post_user_id integer NOT NULL,
|
46
|
+
reply_count integer DEFAULT 0 NOT NULL,
|
47
|
+
featured_user1_id integer,
|
48
|
+
featured_user2_id integer,
|
49
|
+
featured_user3_id integer,
|
50
|
+
avg_time integer,
|
51
|
+
deleted_at timestamp without time zone,
|
52
|
+
highest_post_number integer DEFAULT 0 NOT NULL,
|
53
|
+
image_url character varying,
|
54
|
+
like_count integer DEFAULT 0 NOT NULL,
|
55
|
+
incoming_link_count integer DEFAULT 0 NOT NULL,
|
56
|
+
category_id integer,
|
57
|
+
visible boolean DEFAULT true NOT NULL,
|
58
|
+
moderator_posts_count integer DEFAULT 0 NOT NULL,
|
59
|
+
closed boolean DEFAULT false NOT NULL,
|
60
|
+
archived boolean DEFAULT false NOT NULL,
|
61
|
+
bumped_at timestamp without time zone NOT NULL,
|
62
|
+
has_summary boolean DEFAULT false NOT NULL,
|
63
|
+
vote_count integer DEFAULT 0 NOT NULL,
|
64
|
+
archetype character varying DEFAULT 'regular'::character varying NOT NULL,
|
65
|
+
featured_user4_id integer,
|
66
|
+
notify_moderators_count integer DEFAULT 0 NOT NULL,
|
67
|
+
spam_count integer DEFAULT 0 NOT NULL,
|
68
|
+
pinned_at timestamp without time zone,
|
69
|
+
score double precision,
|
70
|
+
percent_rank double precision DEFAULT 1.0 NOT NULL,
|
71
|
+
subtype character varying,
|
72
|
+
slug character varying,
|
73
|
+
deleted_by_id integer,
|
74
|
+
participant_count integer DEFAULT 1,
|
75
|
+
word_count integer,
|
76
|
+
excerpt character varying(1000),
|
77
|
+
pinned_globally boolean DEFAULT false NOT NULL,
|
78
|
+
pinned_until timestamp without time zone,
|
79
|
+
fancy_title character varying(400),
|
80
|
+
highest_staff_post_number integer DEFAULT 0 NOT NULL,
|
81
|
+
featured_link character varying
|
82
|
+
);
|
83
|
+
|
84
|
+
CREATE TABLE users (
|
85
|
+
id integer NOT NULL PRIMARY KEY,
|
86
|
+
first_name character varying NOT NULL,
|
87
|
+
last_name character varying NOT NULL
|
88
|
+
);
|
89
|
+
CREATE TABLE categories (
|
90
|
+
id integer NOT NULL PRIMARY KEY,
|
91
|
+
name character varying NOT NULL,
|
92
|
+
title character varying NOT NULL,
|
93
|
+
description character varying NOT NULL
|
94
|
+
);
|
95
|
+
SQL
|
96
|
+
|
97
|
+
generate_table(Topic)
|
98
|
+
generate_table(User)
|
99
|
+
generate_table(Category)
|
100
|
+
|
101
|
+
pg.exec <<~SQL
|
102
|
+
CREATE INDEX user_id ON topics USING btree (user_id);
|
103
|
+
CREATE INDEX category_id ON topics USING btree (category_id);
|
104
|
+
SQL
|
105
|
+
|
106
|
+
pg.exec "vacuum full analyze topics"
|
107
|
+
pg.exec "vacuum full analyze users"
|
108
|
+
pg.exec "vacuum full analyze categories"
|
109
|
+
|
110
|
+
[ActiveRecord::Base.connection, db_conn]
|
111
|
+
end
|
112
|
+
|
113
|
+
def generate_table(klass)
|
114
|
+
data =
|
115
|
+
@count_records.times.map do |id|
|
116
|
+
topic = { id: id }
|
117
|
+
klass.columns.each do |c|
|
118
|
+
topic[c.name.to_sym] = value_from_type(c.type)
|
119
|
+
end
|
120
|
+
topic
|
121
|
+
end
|
122
|
+
klass.insert_all(data)
|
123
|
+
end
|
124
|
+
|
125
|
+
def value_from_type(type)
|
126
|
+
case type
|
127
|
+
when :integer then rand(1000)
|
128
|
+
when :datetime then Time.now
|
129
|
+
when :boolean then false
|
130
|
+
else "HELLO WORLD" * 2
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
data/bench/topic_perf.rb
CHANGED
@@ -13,8 +13,9 @@ gemfile do
|
|
13
13
|
gem 'benchmark-ips'
|
14
14
|
gem 'sequel', github: 'jeremyevans/sequel'
|
15
15
|
gem 'sequel_pg', github: 'jeremyevans/sequel_pg', require: 'sequel'
|
16
|
-
gem 'swift-db-postgres', github: 'deepfryed/swift-db-postgres'
|
16
|
+
gem 'swift-db-postgres', github: 'deepfryed/swift-db-postgres' # sudo apt-get install uuid-dev
|
17
17
|
gem 'draper'
|
18
|
+
gem 'pry'
|
18
19
|
end
|
19
20
|
|
20
21
|
require 'sequel'
|
@@ -23,68 +24,14 @@ require 'memory_profiler'
|
|
23
24
|
require 'benchmark/ips'
|
24
25
|
require 'mini_sql'
|
25
26
|
|
26
|
-
|
27
|
-
:adapter => "postgresql",
|
28
|
-
:database => "test_db"
|
29
|
-
)
|
27
|
+
require '../mini_sql/bench/shared/generate_data'
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
SQL
|
38
|
-
|
39
|
-
pg.async_exec <<SQL
|
40
|
-
CREATE TABLE topics (
|
41
|
-
id integer NOT NULL PRIMARY KEY,
|
42
|
-
title character varying NOT NULL,
|
43
|
-
last_posted_at timestamp without time zone,
|
44
|
-
created_at timestamp without time zone NOT NULL,
|
45
|
-
updated_at timestamp without time zone NOT NULL,
|
46
|
-
views integer DEFAULT 0 NOT NULL,
|
47
|
-
posts_count integer DEFAULT 0 NOT NULL,
|
48
|
-
user_id integer,
|
49
|
-
last_post_user_id integer NOT NULL,
|
50
|
-
reply_count integer DEFAULT 0 NOT NULL,
|
51
|
-
featured_user1_id integer,
|
52
|
-
featured_user2_id integer,
|
53
|
-
featured_user3_id integer,
|
54
|
-
avg_time integer,
|
55
|
-
deleted_at timestamp without time zone,
|
56
|
-
highest_post_number integer DEFAULT 0 NOT NULL,
|
57
|
-
image_url character varying,
|
58
|
-
like_count integer DEFAULT 0 NOT NULL,
|
59
|
-
incoming_link_count integer DEFAULT 0 NOT NULL,
|
60
|
-
category_id integer,
|
61
|
-
visible boolean DEFAULT true NOT NULL,
|
62
|
-
moderator_posts_count integer DEFAULT 0 NOT NULL,
|
63
|
-
closed boolean DEFAULT false NOT NULL,
|
64
|
-
archived boolean DEFAULT false NOT NULL,
|
65
|
-
bumped_at timestamp without time zone NOT NULL,
|
66
|
-
has_summary boolean DEFAULT false NOT NULL,
|
67
|
-
vote_count integer DEFAULT 0 NOT NULL,
|
68
|
-
archetype character varying DEFAULT 'regular'::character varying NOT NULL,
|
69
|
-
featured_user4_id integer,
|
70
|
-
notify_moderators_count integer DEFAULT 0 NOT NULL,
|
71
|
-
spam_count integer DEFAULT 0 NOT NULL,
|
72
|
-
pinned_at timestamp without time zone,
|
73
|
-
score double precision,
|
74
|
-
percent_rank double precision DEFAULT 1.0 NOT NULL,
|
75
|
-
subtype character varying,
|
76
|
-
slug character varying,
|
77
|
-
deleted_by_id integer,
|
78
|
-
participant_count integer DEFAULT 1,
|
79
|
-
word_count integer,
|
80
|
-
excerpt character varying(1000),
|
81
|
-
pinned_globally boolean DEFAULT false NOT NULL,
|
82
|
-
pinned_until timestamp without time zone,
|
83
|
-
fancy_title character varying(400),
|
84
|
-
highest_staff_post_number integer DEFAULT 0 NOT NULL,
|
85
|
-
featured_link character varying
|
86
|
-
)
|
87
|
-
SQL
|
29
|
+
ar_connection, conn_config = GenerateData.new(count_records: 1_000).call
|
30
|
+
PG_CONN = ar_connection.raw_connection
|
31
|
+
MINI_SQL = MiniSql::Connection.get(PG_CONN)
|
32
|
+
DB = Sequel.connect(ar_connection.instance_variable_get(:@config).slice(:database, :user, :password, :host, :adapter))
|
33
|
+
# connects over unix socket
|
34
|
+
SWIFT = Swift::DB::Postgres.new(db: conn_config[:database], user: conn_config[:user], password: conn_config[:password], host: conn_config[:host])
|
88
35
|
|
89
36
|
class Topic < ActiveRecord::Base
|
90
37
|
end
|
@@ -92,26 +39,6 @@ end
|
|
92
39
|
class TopicSequel < Sequel::Model(:topics)
|
93
40
|
end
|
94
41
|
|
95
|
-
Topic.transaction do
|
96
|
-
topic = {
|
97
|
-
}
|
98
|
-
Topic.columns.each do |c|
|
99
|
-
topic[c.name.to_sym] = case c.type
|
100
|
-
when :integer then 1
|
101
|
-
when :datetime then Time.now
|
102
|
-
when :boolean then false
|
103
|
-
else "HELLO WORLD" * 2
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
1000.times do |id|
|
108
|
-
topic[:id] = id
|
109
|
-
Topic.create!(topic)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
$conn = ActiveRecord::Base.connection.raw_connection
|
114
|
-
|
115
42
|
def ar_title_id_pluck
|
116
43
|
s = +""
|
117
44
|
Topic.limit(1000).order(:id).pluck(:id, :title).each do |id, title|
|
@@ -133,7 +60,7 @@ end
|
|
133
60
|
def pg_title_id
|
134
61
|
s = +""
|
135
62
|
# use the safe pattern here
|
136
|
-
r =
|
63
|
+
r = PG_CONN.async_exec(-"select id, title from topics order by id limit 1000")
|
137
64
|
|
138
65
|
# this seems fastest despite extra arrays, cause array of arrays is generated
|
139
66
|
# in c code
|
@@ -150,11 +77,9 @@ def pg_title_id
|
|
150
77
|
s
|
151
78
|
end
|
152
79
|
|
153
|
-
$mini_sql = MiniSql::Connection.get($conn)
|
154
|
-
|
155
80
|
def mini_sql_title_id
|
156
81
|
s = +""
|
157
|
-
|
82
|
+
MINI_SQL.query(-"select id, title from topics order by id limit 1000").each do |t|
|
158
83
|
s << t.id.to_s
|
159
84
|
s << t.title
|
160
85
|
end
|
@@ -183,7 +108,7 @@ end
|
|
183
108
|
def mini_sql_title_id_query_single
|
184
109
|
s = +""
|
185
110
|
i = 0
|
186
|
-
r =
|
111
|
+
r = MINI_SQL.query_single(-"select id, title from topics order by id limit 1000")
|
187
112
|
while i < r.length
|
188
113
|
s << r[i].to_s
|
189
114
|
s << r[i + 1]
|
@@ -192,13 +117,10 @@ def mini_sql_title_id_query_single
|
|
192
117
|
s
|
193
118
|
end
|
194
119
|
|
195
|
-
# connects over unix socket
|
196
|
-
$swift = Swift::DB::Postgres.new(db: "test_db")
|
197
|
-
|
198
120
|
def swift_select_title_id(l = 1000)
|
199
121
|
s = +''
|
200
122
|
i = 0
|
201
|
-
r =
|
123
|
+
r = SWIFT.execute("select id, title from topics order by id limit 1000")
|
202
124
|
while i < r.selected_rows
|
203
125
|
s << r.get(i, 0).to_s
|
204
126
|
s << r.get(i, 1)
|
@@ -220,175 +142,6 @@ results = [
|
|
220
142
|
|
221
143
|
exit(-1) unless results.uniq.length == 1
|
222
144
|
|
223
|
-
# https://github.com/drapergem/draper
|
224
|
-
class TopicDraper < Draper::Decorator
|
225
|
-
delegate :id
|
226
|
-
|
227
|
-
def title_bang
|
228
|
-
object.title + '!!!'
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
# https://ruby-doc.org/stdlib-2.5.1/libdoc/delegate/rdoc/SimpleDelegator.html
|
233
|
-
class TopicSimpleDelegator < SimpleDelegator
|
234
|
-
def title_bang
|
235
|
-
title + '!!!'
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
class TopicDecoratorSequel < TopicSequel
|
240
|
-
def title_bang
|
241
|
-
title + '!!!'
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
class TopicArModel < Topic
|
246
|
-
def title_bang
|
247
|
-
title + '!!!'
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
module TopicDecorator
|
252
|
-
def title_bang
|
253
|
-
title + '!!!'
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
Benchmark.ips do |r|
|
258
|
-
r.report('query_decorator') do |n|
|
259
|
-
while n > 0
|
260
|
-
$mini_sql.query_decorator(TopicDecorator, 'select id, title from topics order by id limit 1000').each do |obj|
|
261
|
-
obj.title_bang
|
262
|
-
obj.id
|
263
|
-
end
|
264
|
-
n -= 1
|
265
|
-
end
|
266
|
-
end
|
267
|
-
r.report('extend') do |n|
|
268
|
-
while n > 0
|
269
|
-
$mini_sql.query('select id, title from topics order by id limit 1000').each do |obj|
|
270
|
-
d_obj = obj.extend(TopicDecorator)
|
271
|
-
d_obj.title_bang
|
272
|
-
d_obj.id
|
273
|
-
end
|
274
|
-
n -= 1
|
275
|
-
end
|
276
|
-
end
|
277
|
-
r.report('draper') do |n|
|
278
|
-
while n > 0
|
279
|
-
$mini_sql.query('select id, title from topics order by id limit 1000').each do |obj|
|
280
|
-
d_obj = TopicDraper.new(obj)
|
281
|
-
d_obj.title_bang
|
282
|
-
d_obj.id
|
283
|
-
end
|
284
|
-
n -= 1
|
285
|
-
end
|
286
|
-
end
|
287
|
-
r.report('simple_delegator') do |n|
|
288
|
-
while n > 0
|
289
|
-
$mini_sql.query('select id, title from topics order by id limit 1000').each do |obj|
|
290
|
-
d_obj = TopicSimpleDelegator.new(obj)
|
291
|
-
d_obj.title_bang
|
292
|
-
d_obj.id
|
293
|
-
end
|
294
|
-
n -= 1
|
295
|
-
end
|
296
|
-
end
|
297
|
-
r.report('query') do |n|
|
298
|
-
while n > 0
|
299
|
-
$mini_sql.query('select id, title from topics order by id limit 1000').each do |obj|
|
300
|
-
obj.title + '!!!'
|
301
|
-
obj.id
|
302
|
-
end
|
303
|
-
n -= 1
|
304
|
-
end
|
305
|
-
end
|
306
|
-
r.report('ar model') do |n|
|
307
|
-
while n > 0
|
308
|
-
TopicArModel.limit(1000).order(:id).select(:id, :title).each do |obj|
|
309
|
-
obj.title_bang
|
310
|
-
obj.id
|
311
|
-
end
|
312
|
-
n -= 1
|
313
|
-
end
|
314
|
-
end
|
315
|
-
r.report('sequel model') do |n|
|
316
|
-
while n > 0
|
317
|
-
TopicDecoratorSequel.limit(1000).order(:id).select(:id, :title).each do |obj|
|
318
|
-
obj.title_bang
|
319
|
-
obj.id
|
320
|
-
end
|
321
|
-
n -= 1
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
r.compare!
|
326
|
-
end
|
327
|
-
|
328
|
-
# Comparison:
|
329
|
-
# query: 828.4 i/s
|
330
|
-
# query_decorator: 819.3 i/s - same-ish: difference falls within error
|
331
|
-
# sequel model: 672.4 i/s - 1.23x slower
|
332
|
-
# extend: 519.4 i/s - 1.59x slower
|
333
|
-
# simple_delegator: 496.8 i/s - 1.67x slower
|
334
|
-
# draper: 416.2 i/s - 1.99x slower
|
335
|
-
# ar model: 113.4 i/s - 7.30x slower
|
336
|
-
|
337
|
-
Benchmark.ips do |r|
|
338
|
-
r.report('query_hash') do |n|
|
339
|
-
while n > 0
|
340
|
-
$mini_sql.query_hash('select id, title from topics order by id limit 1000').each do |hash|
|
341
|
-
[hash['id'], hash['title']]
|
342
|
-
end
|
343
|
-
n -= 1
|
344
|
-
end
|
345
|
-
end
|
346
|
-
r.report('query_array') do |n|
|
347
|
-
while n > 0
|
348
|
-
$mini_sql.query_array('select id, title from topics order by id limit 1000').each do |id, title|
|
349
|
-
[id, title]
|
350
|
-
end
|
351
|
-
n -= 1
|
352
|
-
end
|
353
|
-
end
|
354
|
-
r.report('query') do |n|
|
355
|
-
while n > 0
|
356
|
-
$mini_sql.query('select id, title from topics order by id limit 1000').each do |obj|
|
357
|
-
[obj.id, obj.title]
|
358
|
-
end
|
359
|
-
n -= 1
|
360
|
-
end
|
361
|
-
end
|
362
|
-
|
363
|
-
r.compare!
|
364
|
-
end
|
365
|
-
|
366
|
-
# Comparison:
|
367
|
-
# query_array: 1351.6 i/s
|
368
|
-
# query: 963.8 i/s - 1.40x slower
|
369
|
-
# query_hash: 787.4 i/s - 1.72x slower
|
370
|
-
|
371
|
-
Benchmark.ips do |r|
|
372
|
-
r.report('query_single') do |n|
|
373
|
-
while n > 0
|
374
|
-
$mini_sql.query_single('select id from topics order by id limit 1000')
|
375
|
-
n -= 1
|
376
|
-
end
|
377
|
-
end
|
378
|
-
r.report('query_array') do |n|
|
379
|
-
while n > 0
|
380
|
-
$mini_sql.query_array('select id from topics order by id limit 1000').flatten
|
381
|
-
n -= 1
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
|
-
r.compare!
|
386
|
-
end
|
387
|
-
|
388
|
-
# Comparison:
|
389
|
-
# query_single: 2368.9 i/s
|
390
|
-
# query_array: 1350.1 i/s - 1.75x slower
|
391
|
-
|
392
145
|
Benchmark.ips do |r|
|
393
146
|
r.report("ar select title id") do |n|
|
394
147
|
while n > 0
|
@@ -441,71 +194,12 @@ Benchmark.ips do |r|
|
|
441
194
|
r.compare!
|
442
195
|
end
|
443
196
|
|
444
|
-
def wide_topic_ar
|
445
|
-
Topic.first
|
446
|
-
end
|
447
|
-
|
448
|
-
def wide_topic_pg
|
449
|
-
r = $conn.async_exec("select * from topics limit 1")
|
450
|
-
row = r.first
|
451
|
-
r.clear
|
452
|
-
row
|
453
|
-
end
|
454
|
-
|
455
|
-
def wide_topic_sequel
|
456
|
-
TopicSequel.first
|
457
|
-
end
|
458
|
-
|
459
|
-
def wide_topic_mini_sql
|
460
|
-
$conn.query("select * from topics limit 1").first
|
461
|
-
end
|
462
|
-
|
463
|
-
Benchmark.ips do |r|
|
464
|
-
r.report("wide topic ar") do |n|
|
465
|
-
while n > 0
|
466
|
-
wide_topic_ar
|
467
|
-
n -= 1
|
468
|
-
end
|
469
|
-
end
|
470
|
-
r.report("wide topic sequel") do |n|
|
471
|
-
while n > 0
|
472
|
-
wide_topic_sequel
|
473
|
-
n -= 1
|
474
|
-
end
|
475
|
-
end
|
476
|
-
r.report("wide topic pg") do |n|
|
477
|
-
while n > 0
|
478
|
-
wide_topic_pg
|
479
|
-
n -= 1
|
480
|
-
end
|
481
|
-
end
|
482
|
-
r.report("wide topic mini sql") do |n|
|
483
|
-
while n > 0
|
484
|
-
wide_topic_mini_sql
|
485
|
-
n -= 1
|
486
|
-
end
|
487
|
-
end
|
488
|
-
r.compare!
|
489
|
-
end
|
490
|
-
|
491
197
|
# Comparison:
|
492
|
-
# pg select title id:
|
493
|
-
#
|
494
|
-
#
|
495
|
-
# mini_sql select title id:
|
496
|
-
#
|
497
|
-
# sequel title id select:
|
498
|
-
# ar select title id pluck:
|
499
|
-
# ar select title id:
|
500
|
-
#
|
501
|
-
#
|
502
|
-
# Comparison:
|
503
|
-
# wide topic pg: 7474.0 i/s
|
504
|
-
# wide topic mini sql: 7355.2 i/s - same-ish: difference falls within error
|
505
|
-
# wide topic sequel: 5696.8 i/s - 1.31x slower
|
506
|
-
# wide topic ar: 2515.0 i/s - 2.97x slower
|
507
|
-
|
508
|
-
# to run deep analysis run
|
509
|
-
# MemoryProfiler.report do
|
510
|
-
# ar
|
511
|
-
# end.pretty_print
|
198
|
+
# pg select title id: 1315.1 i/s
|
199
|
+
# swift title id: 1268.4 i/s - same-ish: difference falls within error
|
200
|
+
# mini_sql query_single title id: 1206.3 i/s - same-ish: difference falls within error
|
201
|
+
# mini_sql select title id: 1063.8 i/s - 1.24x (± 0.00) slower
|
202
|
+
# sequel title id pluck: 1054.5 i/s - 1.25x (± 0.00) slower
|
203
|
+
# sequel title id select: 814.1 i/s - 1.62x (± 0.00) slower
|
204
|
+
# ar select title id pluck: 667.7 i/s - 1.97x (± 0.00) slower
|
205
|
+
# ar select title id: 215.8 i/s - 6.09x (± 0.00) slower
|