Guest User

Untitled

a guest
Apr 15th, 2018
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.98 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2. #
  3. # JOIN vs HABTM vs INSET benchmark
  4. #
  5.  
  6. require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
  7. require 'benchmark'
  8.  
  9. module ToyApp
  10.  
  11. PERFORMANCE_PGSQL = {
  12. :database => 'benchmark',
  13. :adapter => 'postgresql',
  14. :host => 'localhost',
  15. :username => 'user',
  16. :password => '',
  17. :encoding => 'utf8'
  18. }
  19. PERFORMANCE_MYSQL = {
  20. :database => 'benchmark',
  21. :adapter => 'mysql',
  22. :host => 'localhost',
  23. :username => 'user',
  24. :password => '',
  25. :encoding => 'utf8'
  26. }
  27.  
  28. ActiveRecord::Base.establish_connection PERFORMANCE_MYSQL # Change it on tests
  29.  
  30. class CreatePerformanceDB < ActiveRecord::Migration
  31. def self.up
  32. create_table :posts, :force => true do |t|
  33. t.text :data
  34. end
  35.  
  36. 100.times do
  37. Post.create(:data => Digest::SHA1.hexdigest(rand.to_s))
  38. end
  39.  
  40. # JOIN
  41. create_table :posts_balls, :force => true do |t|
  42. t.integer :post_id, :ball_id
  43. end
  44. create_table :balls, :force => true do |t|
  45. t.text :data
  46. end
  47. add_index :posts_balls, :post_id
  48. add_index :posts_balls, :ball_id
  49.  
  50. 100.times do |i|
  51. Ball.create(:data => Digest::SHA1.hexdigest(rand.to_s))
  52. end
  53.  
  54. # HBTM
  55. create_table :cubes_posts, :id => false, :force => true do |t|
  56. t.integer :post_id, :cube_id
  57. end
  58. create_table :cubes, :force => true do |t|
  59. t.text :data
  60. end
  61. add_index :cubes_posts, :post_id
  62. add_index :cubes_posts, :cube_id
  63.  
  64. 100.times do
  65. Cube.create(:data => Digest::SHA1.hexdigest(rand.to_s))
  66. end
  67. end
  68.  
  69. def self.down
  70. drop_table :posts
  71. drop_table :posts_balls
  72. drop_table :cubes_posts
  73. drop_table :balls
  74. drop_table :cubes
  75. end
  76. end
  77. class Post < ActiveRecord::Base
  78. # JOIN
  79. has_many :post_balls
  80. has_many :balls, :through => :post_balls
  81. # HBTM
  82. has_and_belongs_to_many :cubes
  83.  
  84. # InSet method
  85. def groups
  86. ids = post_balls.map(&:ball_id)
  87. Ball.find(:all, :conditions => ["id in (?)", ids])
  88. end
  89.  
  90. end
  91.  
  92. class PostBall < ActiveRecord::Base
  93. set_table_name 'posts_balls'
  94. belongs_to :post
  95. belongs_to :ball
  96. end
  97.  
  98. class Cube < ActiveRecord::Base
  99. has_and_belongs_to_many :posts
  100. end
  101.  
  102. class Ball < ActiveRecord::Base
  103. has_many :post_balls
  104. has_many :posts, :through => :post_balls
  105.  
  106. # InSet method
  107. def groups
  108. ids = post_balls.map(&:post_id)
  109. Post.find(:all, :conditions => ["id in (?)", ids])
  110. end
  111. end
  112.  
  113. def self.adding
  114. puts "========= ADDING ========="
  115. posts = Post.find(:all)
  116. balls_array = Ball.find(:all)
  117. cubes_array = Cube.find(:all)
  118. Benchmark.bm do |rep|
  119. rep.report("HBTM") do
  120. for post in posts
  121. cubes_array.each{|cube| post.cubes << cube}
  122. end
  123. end
  124. rep.report("JOIN") do
  125. for post in posts
  126. balls_array.each{|ball| post.balls << ball}
  127. end
  128. end
  129. end
  130. end
  131.  
  132. def self.adding_by_groups
  133. puts "========= ADDING BY GROUPS========="
  134. posts = Post.find(:all)
  135. balls_array = Ball.find(:all)
  136. cubes_array = Cube.find(:all)
  137. Benchmark.bm do |rep|
  138. rep.report("HBTM") do
  139. for post in posts
  140. cubes_array.in_groups_of(10){|c| post.cubes << c}
  141. end
  142. end
  143. rep.report("JOIN") do
  144. for post in posts
  145. balls_array.in_groups_of(10){|b| post.balls << b}
  146. end
  147. end
  148. end
  149. end
  150.  
  151. def self.finding
  152. puts "========= FINDING ========="
  153. posts = Post.find(:all)
  154. Benchmark.bm do |rep|
  155. rep.report("HBTM") do
  156. 10.times do
  157. posts.each{|post| post.cubes :all, :group_by => :cube_id}
  158. end
  159. end
  160. rep.report("JOIN") do
  161. 10.times do
  162. posts.each{|post| post.balls :all, :group_by => :ball_id}
  163. end
  164. end
  165. rep.report("INSET") do
  166. 10.times do
  167. posts.each{|c| c.groups }
  168. end
  169. end
  170. end
  171. end
  172.  
  173. def self.finding_back
  174. puts "========= FINDING BACK ========="
  175. balls_array = Ball.find(:all)
  176. cubes_array = Cube.find(:all)
  177. Benchmark.bm do |rep|
  178. rep.report("HBTM") do
  179. 10.times do
  180. cubes_array.each{|c| c.posts :all, :group_by => :post_id}
  181. end
  182. end
  183. rep.report("JOIN") do
  184. 10.times do
  185. balls_array.each{|b| b.posts :all, :group_by => :post_id}
  186. end
  187. end
  188. rep.report("INSET") do
  189. 10.times do
  190. balls_array.each{|c| c.groups }
  191. end
  192. end
  193. end
  194. end
  195.  
  196. CreatePerformanceDB.up
  197. adding
  198. adding_by_groups
  199. finding
  200. finding_back
  201.  
  202. end
  203.  
  204. # edge rails trunk/r8381
  205. # RESULTS:
  206.  
  207. # ++++++++ MYSQL +++++++++
  208. # == ToyApp::CreatePerformanceDB: migrating ====================================
  209. # [...skip...]
  210. # == ToyApp::CreatePerformanceDB: migrated (0.8456s) ===========================
  211. #
  212. # ========= ADDING =========
  213. # user system total real
  214. # HBTM 24.350000 1.270000 25.620000 ( 47.239847)
  215. # JOIN 12.410000 1.550000 13.960000 ( 30.863089)
  216. # ========= ADDING BY GROUPS=========
  217. # user system total real
  218. # HBTM 29.110000 0.580000 29.690000 ( 34.925083)
  219. # JOIN 8.160000 0.730000 8.890000 ( 10.680383)
  220. # ========= FINDING =========
  221. # user system total real
  222. # HBTM 8.830000 0.230000 9.060000 ( 13.733686)
  223. # JOIN 3.780000 0.230000 4.010000 ( 7.609844)
  224. # INSET 7.070000 0.530000 7.600000 ( 7.816038)
  225. # ========= FINDING BACK =========
  226. # user system total real
  227. # HBTM 12.250000 0.240000 12.490000 ( 17.041704)
  228. # JOIN 3.850000 0.180000 4.030000 ( 7.586062)
  229. # INSET 7.280000 0.530000 7.810000 ( 8.170005)
  230. #
  231. # ++++++++ PGSQL +++++++++
  232. # == ToyApp::CreatePerformanceDB: migrating ====================================
  233. # [...skip...]
  234. # == ToyApp::CreatePerformanceDB: migrated (1.1611s) ===========================
  235. #
  236. # ========= ADDING =========
  237. # user system total real
  238. # HBTM 10.470000 1.500000 11.970000 ( 35.073944)
  239. # JOIN 17.470000 1.910000 19.380000 ( 39.107405)
  240. # ========= ADDING BY GROUPS=========
  241. # user system total real
  242. # HBTM 5.600000 0.810000 6.410000 ( 15.075026)
  243. # JOIN 10.370000 0.950000 11.320000 ( 14.386206)
  244. # ========= FINDING =========
  245. # user system total real
  246. # HBTM 7.880000 0.690000 8.570000 ( 10.469631)
  247. # JOIN 5.830000 0.640000 6.470000 ( 7.488131)
  248. # INSET 7.040000 0.760000 7.800000 ( 8.859070)
  249. # ========= FINDING BACK =========
  250. # user system total real
  251. # HBTM 7.590000 0.760000 8.350000 ( 10.211620)
  252. # JOIN 5.470000 0.550000 6.020000 ( 6.913570)
  253. # INSET 7.800000 0.650000 8.450000 ( 9.524528)
Add Comment
Please, Sign In to add comment