O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

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

Ad

PgDay2012 LightningTalk
SQL上級者にこそ知って欲しい


なぜ
O/Rマッパー
             が重要か?
      makoto kuwata <kwa@kuwata-lab.com>
         ...

Ad

問:次のSQLは
何が問題でしょう?



 copyright© 2012 kuwata-lab.com all rights reserved

Ad

SQL
--	 販売成績上位10コを抽出
select	 *	 from	 sales
where	 deleted	 =	 false
order	 by	 amount	 desc
limit	 10

                  ...

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Ad

Confira estes a seguir

1 de 46 Anúncio
1 de 46 Anúncio

Mais Conteúdo rRelacionado

Diapositivos para si

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

  1. 1. PgDay2012 LightningTalk SQL上級者にこそ知って欲しい なぜ 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 sales where deleted = false order by amount desc limit 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 xs end 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 xs end 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 xs end 1つの関数でいろんな ことをやりすぎている copyright© 2012 kuwata-lab.com all rights reserved
  11. 11. 複数の関数に分解 (リファクタリング) copyright© 2012 kuwata-lab.com all rights reserved
  12. 12. Ruby def to_sales(rows) rows.map {|row| Sale.new(*row) } end def active(sales) sales.select {|x| ! x.deleted_at } end def 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. Ruby clas 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 end end 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 sales where deleted = false order by amount desc limit 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 = false class 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 n end に相当する「部分」 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. Ruby class Sales where deleted = false include DataMapper::Resource に相当する「部分」 def self.active where(:deleted => false) end def self.top(n) order(:amount.desc).limit(n) end end 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 departments where 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. サンプルコード: Sequel copyright© 2012 kuwata-lab.com all rights reserved
  33. 33. 副問い合わせを切り出して 名前を付ける Ruby dept_ids = Employee.select(:dept_id) .filter(:age=>20) Department.filter(:id=>dept_ids).all() SQL構築が簡潔になる SQL select * from departments where id in (select dept_id from employees where age = 20) copyright© 2012 kuwata-lab.com all rights reserved
  34. 34. Ruby dept_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 users where date_part('year', age(birth)) < 20 group 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. 年齢の計算式を表す構文木を作り、 Python from sqlalchemy.sql import func as fn age = 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 ORM C, Pascal JDBC, DBI Assembler 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

×