mini_sql 0.2.1 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -1,10 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rake/testtask"
3
5
 
6
+ if RUBY_ENGINE == 'jruby' # Excluding sqlite3 tests
7
+ test_glob = "test/**/{inline_param_encoder_test.rb,postgres/*_test.rb}"
8
+ else
9
+ test_glob = "test/**/*_test.rb"
10
+ end
11
+
4
12
  Rake::TestTask.new(:test) do |t|
5
13
  t.libs << "test"
6
14
  t.libs << "lib"
7
- t.test_files = FileList["test/**/*_test.rb"]
15
+ t.test_files = FileList[test_glob]
8
16
  end
9
17
 
10
- task :default => :test
18
+ task default: :test
@@ -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
- :adapter => "postgresql",
25
- :database => "test_db"
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] = case c.type
59
- when :integer then 1
60
- when :datetime then Time.now
61
- when :boolean then false
62
- else "HELLO WORLD" * 2
63
- end
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,
@@ -0,0 +1,304 @@
1
+ require 'bundler/inline'
2
+
3
+ gemfile do
4
+ source 'https://rubygems.org'
5
+ gem 'mysql2'
6
+ gem 'mini_sql', path: '../'
7
+ gem 'activesupport'
8
+ gem 'activerecord'
9
+ gem 'activemodel'
10
+ gem 'memory_profiler'
11
+ gem 'benchmark-ips'
12
+ gem 'sequel', github: 'jeremyevans/sequel'
13
+ end
14
+
15
+ require 'mysql2'
16
+ require 'sequel'
17
+ require 'active_record'
18
+ require 'memory_profiler'
19
+ require 'benchmark/ips'
20
+ require 'mini_sql'
21
+
22
+ ActiveRecord::Base.establish_connection(
23
+ :adapter => "mysql2",
24
+ :database => "test_db",
25
+ :username => "root",
26
+ :password => ''
27
+ )
28
+
29
+ DB = Sequel.connect("mysql2://root:@localhost/test_db")
30
+
31
+ mysql = ActiveRecord::Base.connection.raw_connection
32
+
33
+ mysql.query <<SQL
34
+ drop table if exists topics
35
+ SQL
36
+
37
+ mysql.query <<~SQL
38
+ CREATE TABLE `topics` (
39
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
40
+ `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
41
+ `last_posted_at` datetime DEFAULT NULL,
42
+ `created_at` datetime NOT NULL,
43
+ `updated_at` datetime NOT NULL,
44
+ `views` int(11) NOT NULL DEFAULT '0',
45
+ `posts_count` int(11) NOT NULL DEFAULT '0',
46
+ `user_id` int(11) DEFAULT NULL,
47
+ `last_post_user_id` int(11) NOT NULL,
48
+ `reply_count` int(11) NOT NULL DEFAULT '0',
49
+ `featured_user1_id` int(11) DEFAULT NULL,
50
+ `featured_user2_id` int(11) DEFAULT NULL,
51
+ `featured_user3_id` int(11) DEFAULT NULL,
52
+ `avg_time` int(11) DEFAULT NULL,
53
+ `deleted_at` datetime DEFAULT NULL,
54
+ `highest_post_number` int(11) NOT NULL DEFAULT '0',
55
+ `image_url` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
56
+ `like_count` int(11) NOT NULL DEFAULT '0',
57
+ `incoming_link_count` int(11) NOT NULL DEFAULT '0',
58
+ `category_id` int(11) DEFAULT NULL,
59
+ `visible` tinyint(1) NOT NULL DEFAULT '1',
60
+ `moderator_posts_count` int(11) NOT NULL DEFAULT '0',
61
+ `closed` tinyint(1) NOT NULL DEFAULT '0',
62
+ `archived` tinyint(1) NOT NULL DEFAULT '0',
63
+ `bumped_at` datetime NOT NULL,
64
+ `has_summary` tinyint(1) NOT NULL DEFAULT '0',
65
+ `archetype` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'regular',
66
+ `featured_user4_id` int(11) DEFAULT NULL,
67
+ `notify_moderators_count` int(11) NOT NULL DEFAULT '0',
68
+ `spam_count` int(11) NOT NULL DEFAULT '0',
69
+ `pinned_at` datetime DEFAULT NULL,
70
+ `score` float DEFAULT NULL,
71
+ `percent_rank` float NOT NULL DEFAULT '1',
72
+ `subtype` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
73
+ `slug` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
74
+ `deleted_by_id` int(11) DEFAULT NULL,
75
+ `participant_count` int(11) DEFAULT '1',
76
+ `word_count` int(11) DEFAULT NULL,
77
+ `excerpt` varchar(1000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
78
+ `pinned_globally` tinyint(1) NOT NULL DEFAULT '0',
79
+ `pinned_until` datetime DEFAULT NULL,
80
+ `fancy_title` varchar(400) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
81
+ `highest_staff_post_number` int(11) NOT NULL DEFAULT '0',
82
+ `featured_link` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
83
+ `reviewable_score` float NOT NULL DEFAULT '0',
84
+ PRIMARY KEY (`id`)
85
+ )
86
+ SQL
87
+
88
+ class Topic < ActiveRecord::Base
89
+ end
90
+
91
+ class TopicSequel < Sequel::Model(:topics)
92
+ end
93
+
94
+ Topic.transaction do
95
+ topic = {
96
+ }
97
+ Topic.columns.each do |c|
98
+ topic[c.name.to_sym] = case c.type
99
+ when :integer then 1
100
+ when :datetime then Time.now
101
+ when :boolean then false
102
+ when :float then 1.0
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
+ def ar_title_id_pluck
116
+ s = +""
117
+ Topic.limit(1000).order(:id).pluck(:id, :title).each do |id, title|
118
+ s << id.to_s
119
+ s << title
120
+ end
121
+ s
122
+ end
123
+
124
+ def ar_title_id
125
+ s = +""
126
+ Topic.limit(1000).order(:id).select(:id, :title).each do |t|
127
+ s << t.id.to_s
128
+ s << t.title
129
+ end
130
+ s
131
+ end
132
+
133
+ def mysql_title_id
134
+ s = +""
135
+ # use the safe pattern here
136
+ r = $conn.query(-"select id, title from topics order by id limit 1000", as: :array)
137
+
138
+ r.each do |row|
139
+ s << row[0].to_s
140
+ s << row[1]
141
+ end
142
+ s
143
+ end
144
+
145
+ $mini_sql = MiniSql::Connection.get($conn)
146
+
147
+ def mini_sql_title_id
148
+ s = +""
149
+ $mini_sql.query(-"select id, title from topics order by id limit 1000").each do |t|
150
+ s << t.id.to_s
151
+ s << t.title
152
+ end
153
+ s
154
+ end
155
+
156
+ def sequel_select_title_id
157
+ s = +""
158
+ TopicSequel.limit(1000).order(:id).select(:id, :title).each do |t|
159
+ s << t.id.to_s
160
+ s << t.title
161
+ end
162
+ s
163
+ end
164
+
165
+ def sequel_pluck_title_id
166
+ s = +""
167
+ TopicSequel.limit(1000).order(:id).select_map([:id, :title]).each do |t|
168
+ s << t[0].to_s
169
+ s << t[1]
170
+ end
171
+ s
172
+ end
173
+
174
+ # usage is not really recommended but just to compare to pluck lets have it
175
+ def mini_sql_title_id_query_single
176
+ s = +""
177
+ i = 0
178
+ r = $mini_sql.query_single(-"select id, title from topics order by id limit 1000")
179
+ while i < r.length
180
+ s << r[i].to_s
181
+ s << r[i + 1]
182
+ i += 2
183
+ end
184
+ s
185
+ end
186
+
187
+ results = [
188
+ ar_title_id,
189
+ ar_title_id_pluck,
190
+ mysql_title_id,
191
+ mini_sql_title_id,
192
+ sequel_pluck_title_id,
193
+ sequel_select_title_id,
194
+ mini_sql_title_id_query_single
195
+ ]
196
+
197
+ exit(-1) unless results.uniq.length == 1
198
+
199
+ Benchmark.ips do |r|
200
+ r.report("ar select title id") do |n|
201
+ while n > 0
202
+ ar_title_id
203
+ n -= 1
204
+ end
205
+ end
206
+ r.report("ar select title id pluck") do |n|
207
+ while n > 0
208
+ ar_title_id_pluck
209
+ n -= 1
210
+ end
211
+ end
212
+ r.report("sequel title id select") do |n|
213
+ while n > 0
214
+ sequel_select_title_id
215
+ n -= 1
216
+ end
217
+ end
218
+ r.report("mysql select title id") do |n|
219
+ while n > 0
220
+ mysql_title_id
221
+ n -= 1
222
+ end
223
+ end
224
+ r.report("mini_sql select title id") do |n|
225
+ while n > 0
226
+ mini_sql_title_id
227
+ n -= 1
228
+ end
229
+ end
230
+ r.report("sequel title id pluck") do |n|
231
+ while n > 0
232
+ sequel_pluck_title_id
233
+ n -= 1
234
+ end
235
+ end
236
+ r.report("mini_sql query_single title id") do |n|
237
+ while n > 0
238
+ mini_sql_title_id_query_single
239
+ n -= 1
240
+ end
241
+ end
242
+ r.compare!
243
+ end
244
+
245
+ def wide_topic_ar
246
+ Topic.first
247
+ end
248
+
249
+ def wide_topic_mysql
250
+ r = $conn.query("select * from topics limit 1", as: :hash)
251
+ row = r.first
252
+ row
253
+ end
254
+
255
+ def wide_topic_sequel
256
+ TopicSequel.first
257
+ end
258
+
259
+ def wide_topic_mini_sql
260
+ $conn.query("select * from topics limit 1").first
261
+ end
262
+
263
+ Benchmark.ips do |r|
264
+ r.report("wide topic ar") do |n|
265
+ while n > 0
266
+ wide_topic_ar
267
+ n -= 1
268
+ end
269
+ end
270
+ r.report("wide topic sequel") do |n|
271
+ while n > 0
272
+ wide_topic_sequel
273
+ n -= 1
274
+ end
275
+ end
276
+ r.report("wide topic mysql") do |n|
277
+ while n > 0
278
+ wide_topic_mysql
279
+ n -= 1
280
+ end
281
+ end
282
+ r.report("wide topic mini sql") do |n|
283
+ while n > 0
284
+ wide_topic_mini_sql
285
+ n -= 1
286
+ end
287
+ end
288
+ r.compare!
289
+ end
290
+
291
+ # Comparison:
292
+ # mysql select title id: 485.0 i/s
293
+ # mini_sql query_single title id: 447.2 i/s - same-ish: difference falls within error
294
+ # mini_sql select title id: 417.4 i/s - 1.16x slower
295
+ # sequel title id pluck: 370.2 i/s - 1.31x slower
296
+ # sequel title id select: 351.0 i/s - 1.38x slower
297
+ # ar select title id pluck: 317.1 i/s - 1.53x slower
298
+ # ar select title id: 102.3 i/s - 4.74x slower
299
+
300
+ # Comparison:
301
+ # wide topic mini sql: 6768.7 i/s
302
+ # wide topic mysql: 6063.9 i/s - same-ish: difference falls within error
303
+ # wide topic sequel: 4908.6 i/s - same-ish: difference falls within error
304
+ # wide topic ar: 2630.2 i/s - 2.57x slower