Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?

75,402 views

Published on

(PgDay2012発表資料) SQLにとって、なぜO/Rマッパーが重要かを説明した資料です。

Published in: Technology
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • ORMはオブジェクトを永続化するだけと思っているのだけど、みんなと考えてるベクトル違うのかな
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • この内容ってO/RマッパーというよりDAOの範囲の話ではないです?
    O/Rマッパーで重要なのは、RDBとモデルを切り離せることだと思います。

    私はそこまで洗練した設計がまだできないので偉そうに言えませんが、
    設計を分けることで、仕様変更でDBとモデル両方の設計を変えなくてもいいとか、そういうメリットがあるんじゃないでしょうか。
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 「カラム変更した時にDTOとDAOの変更をしなくていい」 => 「モデルの変更に強くなる」が一番大きいと思います。
    (Rubyはもともと、DTOの変更は必要ないかもしれません。)
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

SQL上級者こそ知って欲しい、なぜO/Rマッパーが重要か?

  1. 1. PgDay2012 LightningTalkSQL上級者にこそ知って欲しいなぜO/Rマッパー が重要か? makoto kuwata <kwa@kuwata-lab.com> http://www.kuwata-lab.com/
  2. 2. 問:次のSQLは何が問題でしょう? copyright© 2012 kuwata-lab.com all rights reserved
  3. 3. SQL-- 販売成績上位10コを抽出select * from saleswhere deleted = falseorder by amount desclimit 10 文法的には正しいけど… copyright© 2012 kuwata-lab.com all rights reserved
  4. 4. 話は変わって、他のプログラミング言語 copyright© 2012 kuwata-lab.com all rights reserved
  5. 5. Ruby## 販売実績上位Nコを抽出def sales_top(n, rows) xs = rows.map {|row| Sale.new(*row) } xs = xs.select {|x| ! x.deleted_at } xs = xs.sort_by {|x| - x.amount } xs = xs[0, 10] return xsend copyright© 2012 kuwata-lab.com all rights reserved
  6. 6. Ruby## 販売実績上位Nコを抽出def sales_top(n, rows) xs = rows.map {|row| Sale.new(*row) } xs = xs.select {|x| ! x.deleted_at } xs = xs.sort_by {|x| - x.amount } xs = xs[0, 10] select from相当 return xsend copyright© 2012 kuwata-lab.com all rights reserved
  7. 7. Ruby## 販売実績上位Nコを抽出def sales_top(n, rows) xs = rows.map {|row| Sale.new(*row) } xs = xs.select {|x| ! x.deleted_at } xs = xs.sort_by {|x| - x.amount } xs = xs[0, 10] return xs where相当end copyright© 2012 kuwata-lab.com all rights reserved
  8. 8. Ruby## 販売実績上位Nコを抽出def sales_top(n, rows) xs = rows.map {|row| Sale.new(*row) } xs = xs.select {|x| ! x.deleted_at } xs = xs.sort_by {|x| - x.amount } xs = xs[0, 10] return xs order by相当end copyright© 2012 kuwata-lab.com all rights reserved
  9. 9. Ruby## 販売実績上位Nコを抽出def sales_top(n, rows) xs = rows.map {|row| Sale.new(*row) } xs = xs.select {|x| ! x.deleted_at } xs = xs.sort_by {|x| - x.amount } xs = xs[0, 10] return xs limit相当end copyright© 2012 kuwata-lab.com all rights reserved
  10. 10. Ruby## 販売実績上位Nコを抽出def sales_top(n, rows) xs = rows.map {|row| Sale.new(*row) } xs = xs.select {|x| ! x.deleted_at } xs = xs.sort_by {|x| - x.amount } xs = xs[0, 10] return xsend 1つの関数でいろんな ことをやりすぎている copyright© 2012 kuwata-lab.com all rights reserved
  11. 11. 複数の関数に分解(リファクタリング) copyright© 2012 kuwata-lab.com all rights reserved
  12. 12. Rubydef to_sales(rows) rows.map {|row| Sale.new(*row) }enddef active(sales) sales.select {|x| ! x.deleted_at }enddef top(n, sales) sales = sales.sort_by {|x| - x.amount } return sales[0, 10]end copyright© 2012 kuwata-lab.com all rights reserved
  13. 13. Ruby## 使い方def sales_top(n, rows) return top(n, active(to_sales(rows)))end 分解した関数を 組み合わせる copyright© 2012 kuwata-lab.com all rights reserved
  14. 14. 専用のクラスを定義 (オブジェクト指向) copyright© 2012 kuwata-lab.com all rights reserved
  15. 15. Rubyclas Sales def initialize(rows) @all = rows.map {|row| Sales.new(*row) } end attr_reader :all def active @all = @all.select {|x| ! x.deleted } return self end def top(n) @all = @all.sort_by {|x| - x.amount } @all = @all[0, n] return self endend copyright© 2012 kuwata-lab.com all rights reserved
  16. 16. Ruby## 使い方Sales.new(rows).active().top(10).all() 分解したメソッドを 組み合わせる copyright© 2012 kuwata-lab.com all rights reserved
  17. 17. プログラミング言語が持っている基本機能 copyright© 2012 kuwata-lab.com all rights reserved
  18. 18. • 「全体」 「部分」 を に分解する機能• 「部分」 「全体」 から を構築する機能• 「部分」に名前をつけて抽象化する機能 copyright© 2012 kuwata-lab.com all rights reserved
  19. 19. 改めて、次のSQLは何が問題でしょう? copyright© 2012 kuwata-lab.com all rights reserved
  20. 20. SQL-- 販売成績上位10コを抽出select * from saleswhere deleted = falseorder by amount desclimit 10 copyright© 2012 kuwata-lab.com all rights reserved
  21. 21. SQLは、分解・構築・抽象化の機能が弱っちい! copyright© 2012 kuwata-lab.com all rights reserved
  22. 22. そこでO/R Mapper!! copyright© 2012 kuwata-lab.com all rights reserved
  23. 23. ORMを使うことで、•SQLを小さい部品に分解• 部品からSQL全体を構築• 部品に名前をつけて抽象化できるようになる! copyright© 2012 kuwata-lab.com all rights reserved
  24. 24. サンプルコード:ActiveRecord (Rails3) copyright© 2012 kuwata-lab.com all rights reserved
  25. 25. Ruby where deleted = falseclass Sales < ActiveReocrd::Base に相当する「部分」 named_scope :active, {:conditions=>"deleted = false"} named_scope :top, lambda do |n| {:order=>"amount desc", :limit=>n} end order by amount desc limit nend に相当する「部分」 copyright© 2012 kuwata-lab.com all rights reserved
  26. 26. 「部分」を組み合わせて Ruby 「全体」を構築Sales.active().top(10).all()## これは## select * from sales## where deleted = false## order by amount desc limit 10## を生成して実行する ※(2012-12-19) 「と同じ」を「を生成して実行する」に修正 copyright© 2012 kuwata-lab.com all rights reserved
  27. 27. サンプルコード:DataMapper copyright© 2012 kuwata-lab.com all rights reserved
  28. 28. Rubyclass Sales where deleted = false include DataMapper::Resource に相当する「部分」 def self.active where(:deleted => false) end def self.top(n) order(:amount.desc).limit(n) endend order by amount desc limit n に相当する「部分」 copyright© 2012 kuwata-lab.com all rights reserved
  29. 29. 「部分」を組み合わせて Ruby 「全体」を構築Sales.active().top(10).all()## これも## select * from sales## where deleted = false## order by amount desc limit 10## を生成して実行する ※(2012-12-19) 「と同じ」を「を生成して実行する」に修正 copyright© 2012 kuwata-lab.com all rights reserved
  30. 30. 別のサンプル:副問い合わせcopyright© 2012 kuwata-lab.com all rights reserved
  31. 31. SQL-- 年齢が20歳の社員が所属する部署一覧select * from departmentswhere id in (select dept_id from employees where age = 20)order by name SQLに「部品化」の機能が ないことを示す典型例 ※(2012-12-13) "select id" を "select dept_id" に修正 copyright© 2012 kuwata-lab.com all rights reserved
  32. 32. サンプルコード: Sequelcopyright© 2012 kuwata-lab.com all rights reserved
  33. 33. 副問い合わせを切り出して 名前を付ける Rubydept_ids = Employee.select(:dept_id) .filter(:age=>20)Department.filter(:id=>dept_ids).all() SQL構築が簡潔になる SQLselect * from departmentswhere id in (select dept_id from employees where age = 20) copyright© 2012 kuwata-lab.com all rights reserved
  34. 34. Rubydept_ids = Employee.select(:dept_id) .filter(:age=>20)Department.filter(:id=>dept_ids).all()Budget.filter(:dept_id=>dept_ids).all() 部品化した副問い合わせを複数の SQLで共用できる(with句より便利) copyright© 2012 kuwata-lab.com all rights reserved
  35. 35. 別のサンプル:重複した式copyright© 2012 kuwata-lab.com all rights reserved
  36. 36. SQL-- 誕生日をもとに年齢を計算select date_part(year, age(birth)) as age, count(*)from userswhere date_part(year, age(birth)) < 20group by date_part(year, age(birth))order by age 同じ式が重複して出現 copyright© 2012 kuwata-lab.com all rights reserved
  37. 37. サンプルコード:SQLAlchemy copyright© 2012 kuwata-lab.com all rights reserved
  38. 38. 年齢の計算式を表す構文木を作り、 Pythonfrom sqlalchemy.sql import func as fnage = fn.date_part(year, fn.age(User.birth))rows = DBSession .query(age, fn.count(*)) .select_from(User) .filter(age < 20) .group_by(age) .order_by(age) .all() それを複数箇所で使用できる copyright© 2012 kuwata-lab.com all rights reserved
  39. 39. つまりcopyright© 2012 kuwata-lab.com all rights reserved
  40. 40. • SQLには部品化の機能がない → SQLが長くなる・わかりにくい → 複数のSQLで要素の重複が多い• ORMはSQL要素の部品化ができる → SQL構築が簡潔・わかりやすい → 複数のSQLで部品を共用できる copyright© 2012 kuwata-lab.com all rights reserved
  41. 41. • SQLには部品化の機能がない → SQLが長くなる・わかりにくい → 複数のSQLで要素の重複が多い• ORMはSQL要素の部品化ができる → SQL構築が簡潔・わかりやすい → 複数のSQLで部品を共用できる copyright© 2012 kuwata-lab.com all rights reserved
  42. 42. たとえるならcopyright© 2012 kuwata-lab.com all rights reserved
  43. 43. まだ進化の途中な 高水準へと進化 ので暖かい目を!Lisp, Ruby Modern ORMC, Pascal JDBC, DBIAssembler SQL 低水準から copyright© 2012 kuwata-lab.com all rights reserved
  44. 44. まとめcopyright© 2012 kuwata-lab.com all rights reserved
  45. 45. • 一般のプログラミング言語には 「分解」「構築」「抽象化」 の機能がある• SQLはそれらが弱っちい• モダンなORMなら、それらの機能 をSQLに提供できる ORMはSQLの高水準言語 or DSL! copyright© 2012 kuwata-lab.com all rights reserved
  46. 46. おしまいcopyright© 2012 kuwata-lab.com all rights reserved

×