Top Banner
イケテル better nested set 研究会 藤岡岳之(xibbar)
26

More Better Nested Set

May 19, 2015

Download

Technology

xibbar
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: More Better Nested Set

イケテルbetter nested set

研究会藤岡岳之(xibbar)

Page 2: More Better Nested Set

アジェンダ

better nested setを使って組織図を書く手軽に書きたいんだ~!

Page 3: More Better Nested Set

Sectionモデルを作成1

better nested setをインストール

Page 4: More Better Nested Set

Sectionモデルを作成2migrationファイルモデルはSectionという名前にすることにして、使用するカラムはnameだけにbetter nested setにはparent_id、lft、rgtという:integerなカラムが必要

class CreateSections < ActiveRecord::Migration def self.up create_table :sections do |t| t.column :name, :string, :null=>false t.column :parent_id, :integer t.column :lft, :integer t.column :rgt, :integer end end def self.down drop_table :sections endend

Page 5: More Better Nested Set

Sectionモデルを作成3

app/models/section.rbの中身

class Section < ActiveRecord::Base acts_as_nested_set

end

Page 6: More Better Nested Set

データを作成

ツリーを作成してみる% ./script/runner 'Section.create(:name=>"日本Ruby会議")'% ./script/runner 'Section.create(:name=>"東京Ruby会議").move_to_child_of Section.find_by_name("日本Ruby会議")'% ./script/runner 'Section.create(:name=>"札幌Ruby会議").move_to_child_of Section.find_by_name("日本Ruby会議")' % ./script/runner 'Section.create(:name=>"Akasaka.rb").move_to_child_of Section.find_by_name("東京Ruby会議")'% ./script/runner 'Section.create(:name=>"Asakusa.rb").move_to_child_of Section.find_by_name("東京Ruby会議")'

DBの中身は# select * from sections; id | name | parent_id | lft | rgt ----+--------------+-----------+-----+----- 1 | 日本Ruby会議 | | 1 | 10 2 | 東京Ruby会議 | 1 | 2 | 7 3 | 札幌Ruby会議 | 1 | 8 | 9 4 | Akasaka.rb | 2 | 3 | 4 5 | Asakusa.rb | 2 | 5 | 6(5 rows)

Page 8: More Better Nested Set

モデルに一行追加

class Section < ActiveRecord::Base acts_as_nested_set acts_as_section_mapend

※ acts_as_section_mapは  acts_as_nested_setの下に書くこと

Page 9: More Better Nested Set

コントローラー

class WelcomeController <ApplicationController def index @table2=Section.table2 endend

1行追加

Page 10: More Better Nested Set

ビュー

<% section_map(@table2) do |table| %> <%=table.name%> <% end %>

index.rhtml

※ テーブルの中身はブロックで指定

※ プラグインの魔法で、たったこれだけで組織図完成

Page 11: More Better Nested Set

関連テーブル

class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.column :name, :string, :null=>false t.column :section_id, :integer end end def self.down drop_table :users endend

user.rb

class User < ActiveRecord::Base belongs_to :sectionend

section.rbclass Section < ActiveRecord::Base acts_as_nested_set acts_as_section_map has_many :usersend

Page 12: More Better Nested Set

データ作成

% ./script/runner 'Section.find_by_name("Akasaka.rb").users << User.create(:name=>"takai")'% ./script/runner 'Section.find_by_name("Akasaka.rb").users << User.create(:name=>"koichiroo")'% ./script/runner 'Section.find_by_name("Akasaka.rb").users << User.create(:name=>"takedasoft")'% ./script/runner 'Section.find_by_name("Asakusa.rb").users << User.create(:name=>"a_matsuda")' % ./script/runner 'Section.find_by_name("Asakusa.rb").users << User.create(:name=>"kakutani")' % ./script/runner 'Section.find_by_name("Asakusa.rb").users << User.create(:name=>"maiha")'

userを作成し、sectionにぶら下げる

Page 13: More Better Nested Set

ビューも直す

<% section_map(@table2) do |table| %> <%=table.name%> <ul> <% table.users.each do |user|%> <li><%=user.name%></li> <%end%> </ul><% end %>

index.rhtml

Page 14: More Better Nested Set

見た目を直そう

<% section_map(@table2,:table=>{:cellspacing=>"0",:style=>"border-collapse:collapse;"}, :td=>{:valign=>"top",:style=>"border:1px solid #666666;color:navy;"}) do |table| %> <%=table.name%> <ul> <% table.users.each do |user|%> <li style="font-size:12px;color:green"><%=user.name%></li> <%end%> </ul><% end %>

index.rhtml

Page 15: More Better Nested Set

のろくない?

数が多いとのろいぞでも、なんとかしちゃるでも今日はおしまい続きは次回以降

Page 16: More Better Nested Set

イケテルDBチューニング

xibbarこと藤岡岳之

Page 17: More Better Nested Set

ブログのぶくま

Page 18: More Better Nested Set

これでぎりぎり卒論になるんじゃなかろうか。長谷川がこけたら、これにしようかな。。。

なんだこれ!!

Page 19: More Better Nested Set

巨大な組織

(1..4).each{|n|Section.create(:name=>"Section:#{n}")}(5..60).each{|n|2.times{|m|Section.find_or_create_by_name("Section:#{n*2+m+3}").move_to_child_of Section.find_by_name("Section:#{n}")}}

120組織のツリーを作るスクリプト

Page 20: More Better Nested Set

遅すぎる

User Load (0.000204) SELECT * FROM users WHERE (users.section_id = 124) Completed in 18.13171 (0 reqs/sec) | Rendering: 7.49291 (41%) | DB: 10.46457 (57%) | 200 OK [http://localhost/welcome]

表示に18秒っておい!

Page 21: More Better Nested Set

インデックスを張ってみる

User Load (0.000182) SELECT * FROM users WHERE (users.section_id = 124) Completed in 10.01978 (0 reqs/sec) | Rendering: 6.97071 (69%) | DB: 2.87357 (28%) | 200 OK [http://localhost/welcome]

10秒に短縮!まだ使い物にならないけど

Page 22: More Better Nested Set

すばやさの種を投入class AddDepthToSections < ActiveRecord::Migration def self.up add_column :sections,:depth,:integer Section.set_depth end

def self.down remove_column :sections,:depth endend

depthという項目を追加し、値をセットする。depthというのは文字通り深さの値(levelの結果)

Page 23: More Better Nested Set

すばやさの種の結果

User Load (0.000180) SELECT * FROM users WHERE (users.section_id = 124) Completed in 0.84391 (1 reqs/sec) | Rendering: 0.40329 (47%) | DB: 0.27316 (32%) | 200 OK [http://localhost/welcome]

1秒切ってメデタシメデタシ

Page 24: More Better Nested Set

ちょっとだけ解説

のろさの原因はsectionが自分自身の深さを知るためにselect count(*)していることにある。(levelメソッド)これをカラムとして持つとツリーの構築の早さが圧倒的に違う(つまりdepthカラム)

Page 25: More Better Nested Set

benchmark% ./script/performance/benchmarker 100 'Section.find(:all).map(&:level)' user system total real#1 5.790000 0.470000 6.260000 ( 10.331682)

% ./script/performance/benchmarker 100 'Section.find(:all).map(&:depth)' user system total real#1 0.610000 0.010000 0.620000 ( 0.784886)

% ./script/performance/benchmarker 100 'Section.find(:all).map(&:level)' user system total real#1 6.180000 0.530000 6.710000 ( 20.693455)

ちなみにindex張る前は

20.693÷0.784=26.39426倍早くなった!!

Page 26: More Better Nested Set

グー

おしまい

http://www001.upp.so-net.ne.jp/masa_gallery/edo.html