mini_sql 0.2.4 → 0.2.5
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/.rubocop-https---raw-githubusercontent-com-discourse-discourse-master--rubocop-yml +355 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +3 -1
- data/CHANGELOG +4 -0
- data/Gemfile +3 -1
- data/Guardfile +2 -0
- data/README.md +60 -1
- data/Rakefile +3 -1
- data/bench/timestamp_perf.rb +22 -21
- data/bench/topic_mysql_perf.rb +1 -7
- data/bench/topic_perf.rb +174 -10
- data/bin/console +1 -0
- data/lib/mini_sql/builder.rb +0 -1
- data/lib/mini_sql/connection.rb +1 -1
- data/lib/mini_sql/deserializer_cache.rb +2 -0
- data/lib/mini_sql/inline_param_encoder.rb +9 -9
- data/lib/mini_sql/mysql/connection.rb +12 -3
- data/lib/mini_sql/mysql/deserializer_cache.rb +7 -3
- data/lib/mini_sql/postgres/coders.rb +2 -0
- data/lib/mini_sql/postgres/connection.rb +17 -0
- data/lib/mini_sql/postgres/deserializer_cache.rb +7 -4
- data/lib/mini_sql/postgres_jdbc/connection.rb +5 -0
- data/lib/mini_sql/postgres_jdbc/deserializer_cache.rb +45 -41
- data/lib/mini_sql/sqlite/connection.rb +11 -1
- data/lib/mini_sql/sqlite/deserializer_cache.rb +7 -3
- data/lib/mini_sql/version.rb +1 -1
- data/mini_sql.gemspec +5 -1
- metadata +32 -2
data/Rakefile
CHANGED
data/bench/timestamp_perf.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/inline'
|
2
4
|
|
3
5
|
gemfile do
|
@@ -21,8 +23,8 @@ require 'benchmark/ips'
|
|
21
23
|
require 'mini_sql'
|
22
24
|
|
23
25
|
ActiveRecord::Base.establish_connection(
|
24
|
-
:
|
25
|
-
:
|
26
|
+
adapter: "postgresql",
|
27
|
+
database: "test_db"
|
26
28
|
)
|
27
29
|
|
28
30
|
Sequel.default_timezone = :utc
|
@@ -47,20 +49,20 @@ SQL
|
|
47
49
|
class Timestamp < ActiveRecord::Base
|
48
50
|
end
|
49
51
|
|
50
|
-
class TimestampSequel< Sequel::Model(:timestamps)
|
52
|
+
class TimestampSequel < Sequel::Model(:timestamps)
|
51
53
|
end
|
52
54
|
|
53
|
-
|
54
55
|
Timestamp.transaction do
|
55
56
|
stamps = {
|
56
57
|
}
|
57
58
|
Timestamp.columns.each do |c|
|
58
|
-
stamps[c.name.to_sym] =
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
59
|
+
stamps[c.name.to_sym] =
|
60
|
+
case c.type
|
61
|
+
when :integer then 1
|
62
|
+
when :datetime then Time.now
|
63
|
+
when :boolean then false
|
64
|
+
else "HELLO WORLD" * 2
|
65
|
+
end
|
64
66
|
end
|
65
67
|
|
66
68
|
1000.times do |id|
|
@@ -71,7 +73,7 @@ end
|
|
71
73
|
|
72
74
|
$conn = ActiveRecord::Base.connection.raw_connection
|
73
75
|
|
74
|
-
def ar_pluck_times(l=1000)
|
76
|
+
def ar_pluck_times(l = 1000)
|
75
77
|
s = +""
|
76
78
|
Timestamp.limit(l).order(:id).pluck(:time1, :time2).each do |time1, time2|
|
77
79
|
s << time1.to_f.to_s
|
@@ -80,7 +82,7 @@ def ar_pluck_times(l=1000)
|
|
80
82
|
s
|
81
83
|
end
|
82
84
|
|
83
|
-
def ar_select_times(l=1000)
|
85
|
+
def ar_select_times(l = 1000)
|
84
86
|
s = +""
|
85
87
|
Timestamp.limit(l).order(:id).select(:time1, :time2).each do |t|
|
86
88
|
s << t.time1.to_f.to_s
|
@@ -91,7 +93,7 @@ end
|
|
91
93
|
|
92
94
|
$mini_sql = MiniSql::Connection.new($conn)
|
93
95
|
|
94
|
-
def pg_times_params(l=1000)
|
96
|
+
def pg_times_params(l = 1000)
|
95
97
|
s = +""
|
96
98
|
# use the safe pattern here
|
97
99
|
r = $conn.async_exec_params(-"select time1, time2 from timestamps order by id limit $1", [l])
|
@@ -110,7 +112,7 @@ def pg_times_params(l=1000)
|
|
110
112
|
s
|
111
113
|
end
|
112
114
|
|
113
|
-
def pg_times(l=1000)
|
115
|
+
def pg_times(l = 1000)
|
114
116
|
s = +""
|
115
117
|
# use the safe pattern here
|
116
118
|
r = $conn.async_exec("select time1, time2 from timestamps order by id limit #{l}")
|
@@ -129,7 +131,7 @@ def pg_times(l=1000)
|
|
129
131
|
s
|
130
132
|
end
|
131
133
|
|
132
|
-
def mini_sql_times(l=1000)
|
134
|
+
def mini_sql_times(l = 1000)
|
133
135
|
s = +""
|
134
136
|
$mini_sql.query(-"select time1, time2 from timestamps order by id limit ?", l).each do |t|
|
135
137
|
s << t.time1.to_f.to_s
|
@@ -138,7 +140,7 @@ def mini_sql_times(l=1000)
|
|
138
140
|
s
|
139
141
|
end
|
140
142
|
|
141
|
-
def sequel_times(l=1000)
|
143
|
+
def sequel_times(l = 1000)
|
142
144
|
s = +""
|
143
145
|
TimestampSequel.limit(l).order(:id).select(:time1, :time2).each do |t|
|
144
146
|
s << t.time1.to_f.to_s
|
@@ -147,7 +149,7 @@ def sequel_times(l=1000)
|
|
147
149
|
s
|
148
150
|
end
|
149
151
|
|
150
|
-
def sequel_pluck_times(l=1000)
|
152
|
+
def sequel_pluck_times(l = 1000)
|
151
153
|
s = +""
|
152
154
|
TimestampSequel.limit(l).order(:id).select_map([:time1, :time2]).each do |t|
|
153
155
|
s << t[0].to_f.to_s
|
@@ -156,7 +158,7 @@ def sequel_pluck_times(l=1000)
|
|
156
158
|
s
|
157
159
|
end
|
158
160
|
|
159
|
-
def sequel_raw_times(l=1000)
|
161
|
+
def sequel_raw_times(l = 1000)
|
160
162
|
s = +""
|
161
163
|
DB[-"select time1, time2 from timestamps order by id limit ?", l].map([:time1, :time2]).each do |time1, time2|
|
162
164
|
s << time1.to_f.to_s
|
@@ -166,13 +168,13 @@ def sequel_raw_times(l=1000)
|
|
166
168
|
end
|
167
169
|
|
168
170
|
# usage is not really recommended but just to compare to pluck lets have it
|
169
|
-
def mini_sql_times_single(l=1000)
|
171
|
+
def mini_sql_times_single(l = 1000)
|
170
172
|
s = +""
|
171
173
|
i = 0
|
172
174
|
r = $mini_sql.query_single(-"select time1, time2 from timestamps order by id limit ?", l)
|
173
175
|
while i < r.length
|
174
176
|
s << r[i].to_f.to_s
|
175
|
-
s << r[i+1].to_f.to_s
|
177
|
+
s << r[i + 1].to_f.to_s
|
176
178
|
i += 2
|
177
179
|
end
|
178
180
|
s
|
@@ -190,7 +192,6 @@ end
|
|
190
192
|
# s
|
191
193
|
# end
|
192
194
|
|
193
|
-
|
194
195
|
results = [
|
195
196
|
ar_select_times,
|
196
197
|
ar_pluck_times,
|
data/bench/topic_mysql_perf.rb
CHANGED
@@ -91,7 +91,6 @@ end
|
|
91
91
|
class TopicSequel < Sequel::Model(:topics)
|
92
92
|
end
|
93
93
|
|
94
|
-
|
95
94
|
Topic.transaction do
|
96
95
|
topic = {
|
97
96
|
}
|
@@ -179,7 +178,7 @@ def mini_sql_title_id_query_single
|
|
179
178
|
r = $mini_sql.query_single(-"select id, title from topics order by id limit 1000")
|
180
179
|
while i < r.length
|
181
180
|
s << r[i].to_s
|
182
|
-
s << r[i+1]
|
181
|
+
s << r[i + 1]
|
183
182
|
i += 2
|
184
183
|
end
|
185
184
|
s
|
@@ -197,7 +196,6 @@ results = [
|
|
197
196
|
|
198
197
|
exit(-1) unless results.uniq.length == 1
|
199
198
|
|
200
|
-
|
201
199
|
Benchmark.ips do |r|
|
202
200
|
r.report("ar select title id") do |n|
|
203
201
|
while n > 0
|
@@ -244,8 +242,6 @@ Benchmark.ips do |r|
|
|
244
242
|
r.compare!
|
245
243
|
end
|
246
244
|
|
247
|
-
|
248
|
-
|
249
245
|
def wide_topic_ar
|
250
246
|
Topic.first
|
251
247
|
end
|
@@ -301,10 +297,8 @@ end
|
|
301
297
|
# ar select title id pluck: 317.1 i/s - 1.53x slower
|
302
298
|
# ar select title id: 102.3 i/s - 4.74x slower
|
303
299
|
|
304
|
-
|
305
300
|
# Comparison:
|
306
301
|
# wide topic mini sql: 6768.7 i/s
|
307
302
|
# wide topic mysql: 6063.9 i/s - same-ish: difference falls within error
|
308
303
|
# wide topic sequel: 4908.6 i/s - same-ish: difference falls within error
|
309
304
|
# wide topic ar: 2630.2 i/s - 2.57x slower
|
310
|
-
|
data/bench/topic_perf.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/inline'
|
2
4
|
|
3
5
|
gemfile do
|
@@ -12,6 +14,7 @@ gemfile do
|
|
12
14
|
gem 'sequel', github: 'jeremyevans/sequel'
|
13
15
|
gem 'sequel_pg', github: 'jeremyevans/sequel_pg', require: 'sequel'
|
14
16
|
gem 'swift-db-postgres', github: 'deepfryed/swift-db-postgres'
|
17
|
+
gem 'draper'
|
15
18
|
end
|
16
19
|
|
17
20
|
require 'sequel'
|
@@ -89,7 +92,6 @@ end
|
|
89
92
|
class TopicSequel < Sequel::Model(:topics)
|
90
93
|
end
|
91
94
|
|
92
|
-
|
93
95
|
Topic.transaction do
|
94
96
|
topic = {
|
95
97
|
}
|
@@ -184,7 +186,7 @@ def mini_sql_title_id_query_single
|
|
184
186
|
r = $mini_sql.query_single(-"select id, title from topics order by id limit 1000")
|
185
187
|
while i < r.length
|
186
188
|
s << r[i].to_s
|
187
|
-
s << r[i+1]
|
189
|
+
s << r[i + 1]
|
188
190
|
i += 2
|
189
191
|
end
|
190
192
|
s
|
@@ -193,8 +195,8 @@ end
|
|
193
195
|
# connects over unix socket
|
194
196
|
$swift = Swift::DB::Postgres.new(db: "test_db")
|
195
197
|
|
196
|
-
def swift_select_title_id(l=1000)
|
197
|
-
s =
|
198
|
+
def swift_select_title_id(l = 1000)
|
199
|
+
s = +''
|
198
200
|
i = 0
|
199
201
|
r = $swift.execute("select id, title from topics order by id limit 1000")
|
200
202
|
while i < r.selected_rows
|
@@ -218,6 +220,174 @@ results = [
|
|
218
220
|
|
219
221
|
exit(-1) unless results.uniq.length == 1
|
220
222
|
|
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
|
221
391
|
|
222
392
|
Benchmark.ips do |r|
|
223
393
|
r.report("ar select title id") do |n|
|
@@ -271,8 +441,6 @@ Benchmark.ips do |r|
|
|
271
441
|
r.compare!
|
272
442
|
end
|
273
443
|
|
274
|
-
|
275
|
-
|
276
444
|
def wide_topic_ar
|
277
445
|
Topic.first
|
278
446
|
end
|
@@ -320,7 +488,6 @@ Benchmark.ips do |r|
|
|
320
488
|
r.compare!
|
321
489
|
end
|
322
490
|
|
323
|
-
|
324
491
|
# Comparison:
|
325
492
|
# pg select title id: 1519.7 i/s
|
326
493
|
# mini_sql query_single title id: 1335.0 i/s - 1.14x slower
|
@@ -338,10 +505,7 @@ end
|
|
338
505
|
# wide topic sequel: 5696.8 i/s - 1.31x slower
|
339
506
|
# wide topic ar: 2515.0 i/s - 2.97x slower
|
340
507
|
|
341
|
-
|
342
|
-
|
343
508
|
# to run deep analysis run
|
344
509
|
# MemoryProfiler.report do
|
345
510
|
# ar
|
346
511
|
# end.pretty_print
|
347
|
-
|
data/bin/console
CHANGED
data/lib/mini_sql/builder.rb
CHANGED
data/lib/mini_sql/connection.rb
CHANGED
@@ -4,7 +4,7 @@ module MiniSql
|
|
4
4
|
class Connection
|
5
5
|
|
6
6
|
def self.get(raw_connection, options = {})
|
7
|
-
if (defined? ::PG::Connection) && (PG::Connection === raw_connection)
|
7
|
+
if (defined? ::PG::Connection) && (PG::Connection === raw_connection)
|
8
8
|
Postgres::Connection.new(raw_connection, options)
|
9
9
|
elsif (defined? ::ArJdbc)
|
10
10
|
Postgres::Connection.new(raw_connection, options)
|