Your SlideShare is downloading. ×
  • Like
ふくよかなモデル
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

ふくよかなモデル

  • 477 views
Published

 

Published in Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
477
On SlideShare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
0
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. DBAからRailsエンジニアになってモデルがふくよかなことに気がついた
  • 2. 自己紹介名前:三浦 美咲樹@yukainaTokyu.rbとYokohama.rbに、参加させてもらっています。昨年(2012年)8月から、念願のRailsのエンジニアになりました。
  • 3. Railsやる前はデータベースエンジニアをやっていました。PostgreSQLもっと前には、MySQL、Oracle、SQLServer・・・etc
  • 4. DBAとは言っても開発もやっていました。言語はP・・
  • 5. DBAとは言ってもRailsっぽいフレームワークSymfony、CakePHPのプロジェクトも有りました。なので・・・
  • 6. DBAとは言ってもRailsとかフレームワークを、意識したテーブル設計とか、いい感じで、モデルを生成できてると・・・思っていた2012年の初夏でした。
  • 7. まず最初に思っていたよりも、奥が深かったので、もっと、勉強が必要でした・・・そろそろ本題
  • 8. 気になるとこ•MVCパターン
  • 9. MVCパターン• Model• View• Controller• Model
  • 10. Modelのイメージ
  • 11. RailsのModel
  • 12. なんだろ?この差は
  • 13. 産まれたてのModelclass User < ActiveRecord::Baseattr_accessible :name, :birthday, :profileend
  • 14. 育ってくModelclass User < ActiveRecord::Baseattr_accessible :name, :birthday, :job, :profilevalidates :name, :birthday, :job, :profile presence: truevalidates :name, uniqueness: truedef xxxenddef yyyenddef zzzend ・  ・ ・endで、すくすく育った結果が・・・
  • 15. 育ったModel育ちすぎちゃう?
  • 16. なんで?ビジネスロジックをModelに書くから?
  • 17. 振り返ってみる。いままで、経験してきたプロジェクトって、ビジネスロジックってどうしてたん?アクションに書いていたん?ほんとに? ?
  • 18. そういえば。Javaのプロジェクトも経験していた!確か、S2StrutsとかS2Daoとかってやつ。
  • 19. 見てみた。SAStrutsだけど。
  • 20. 見てみた。SAStrutsだけど。
  • 21. エンティティ
  • 22. 見てみた。SAStrutsだけど。ビジネスロジック?
  • 23. ビジネスロジックは?
  • 24. サービス?
  • 25. こういうこと?ビジネスロジック?
  • 26. ∑( ̄Д ̄;)
  • 27. サービスっての忘れてた。ようするに
  • 28. ビジネスロジックは?
  • 29. そういうこと?ビジネスロジック
  • 30. 頭の中では肝心のサービスが抜けてたビジネスロジック?ビジネスロジック
  • 31. 正しくはビジネスロジック
  • 32. やっぱりいままで、経験してきたプロジェクトって、ビジネスロジックどうしてたん?サービスというものをわすれていたからには、アクションに書いていたのかもしれない
  • 33. RailsのModelの役割• データベースとやり取りするところCRUDORマッピング• ビジネスロジック• バリデーション• SQL文生成,etc
  • 34. モデルがふくよかなのは、仕方がないのかもしれない。RailsのModelの役割
  • 35. とはいえ、スタイルの良いモデルに憧れるよねぇ∼
  • 36. とはいえ、誰か、モデルのスリム化を。。。
  • 37. と、言うことでモデルがふくよかなのは、仕方がないのかもしれないのですが、スタイルの良いモデル・・・探してみると
  • 38. 多対多ふくよかになりがちなモデルの中でも、多対多の中間テーブルのモデルは、スタイルが良い・・・ほぼ産まれたまま。でも、データ量は大きくなりがち
  • 39. 元DBAとしては、データサイズとか、気になってしまうんですよねぇ∼
  • 40. と、言うことでデータベース (MySQL) のスリム化について考えてみた!
  • 41. 多対多10,000件 25,000,000件 10,000件
  • 42. class CreateUsersGroups < ActiveRecord::Migrationdef changecreate_table :users_groups do | t |t.references :usert.references :groupendendend多対多
  • 43. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+---------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+---------+----------+-----------+| users_groups | InnoDB | 25000572 | 34 | 811.00 | 811.00 | 0.00 || users | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 9744 | 47 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+---------+----------+-----------+多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 44. 多対多10,000件 25,000,000件 10,000件
  • 45. MySQLのINTのバイト
  • 46. 多対多10,000件 25,000,000件 10,000件
  • 47. class CreateUsersGroups < ActiveRecord::Migrationdef changecreate_table :users_groups, :id => false do | t |t.references :usert.references :groupendendend多対多
  • 48. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+---------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+---------+----------+-----------+| users_groups | InnoDB | 25000427 | 36 | 862.00 | 862.00 | 0.00 || users | InnoDB | 9062 | 50 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+---------+----------+-----------+多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 49. 多対多811MB平均 34byte862MB平均 36byte10,000件 25,000,000件 10,000件
  • 50. 平均サイズが2バイト増加!2バイト × 2500万 = 50 MB 増加!多対多∑( ̄Д ̄;)
  • 51. 平均行サイズが4バイト減・・・4バイト × 2500万 = 100 MB 減・・・だったはずちゃう?多対多
  • 52. idの4バイト分、節約ちゃうかった?なのに、2バイト増えてんで。。。多対多
  • 53. なんで、増えんねん・・・・原因は・・・多対多
  • 54. クラスタインデックスhttp://dev.mysql.com/doc/refman/5.1-olh/ja/innodb-index-
  • 55. クラスタインデックスMySQLのInnoDBには、クラスタインデックスというのがある
  • 56. 通常のインデックス
  • 57. クラスタインデックス
  • 58. クラスタインデックス• テーブルに PRIMARY KEY がある場合、それをクラスタインデックスとする• テーブルに PRIMARY KEY が無い場合、 NOT NULL カラムだけを持つ最初のUNIQUE インデックス をクラスタインデックスとする• テーブルに PRIMARY KEY も適切な UNIQUE インデックスもない場合は、InnoDB の内部で、行 ID 値を含む合成カラム上に隠しクラスタインデックスが生成される。行 ID は、新しい行が挿入されると単調に増加する 6 バイトのフィールド
  • 59. 多対多
  • 60. • テーブルに PRIMARY KEY がある場合、それをクラスタインデックスとする• テーブルに PRIMARY KEY が無い場合、 NOT NULL カラムだけを持つ最初のUNIQUE インデックス をクラスタインデックスとする• テーブルに PRIMARY KEY も適切な UNIQUE インデックスもない場合は、InnoDB の内部で、行 ID 値を含む合成カラム上に隠しクラスタインデックスが生成される。行 ID は、新しい行が挿入されると単調に増加する 6 バイトのフィールドクラスタインデックス• テーブルに PRIMARY KEY がある場合、それをクラスタインデックスとする• テーブルに PRIMARY KEY が無い場合、 NOT NULL カラムだけを持つ最初のUNIQUE インデックス をクラスタインデックスとする• テーブルに PRIMARY KEY も適切な UNIQUE インデックスもない場合は、InnoDB の内部で、行 ID 値を含む合成カラム上に隠しクラスタインデックスが生成される。行 ID は、新しい行が挿入されると単調に増加する 6 バイトのフィールド
  • 61. 多対多
  • 62. 平均サイズが2バイト増加!2バイト × 2500万 = 50 MB 増加!多対多
  • 63. 多対多
  • 64. class CreateUsersGroups < ActiveRecord::Migrationdef changecreate_table :users_groups, :id => false do | t |t.references :usert.references :groupendadd_index :users_groups, :user_idadd_index :users_groups, :group_idendend多対多
  • 65. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+----------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+----------+----------+-----------+| users_groups | InnoDB | 25000427 | 36 | 1,870.00 | 862.00 | 1,008.00 || users | InnoDB | 9744 | 47 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+----------+----------+-----------+4 rows in set (0.02 sec)多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 66. 多対多
  • 67. • テーブルに PRIMARY KEY がある場合、それをクラスタインデックスとする• テーブルに PRIMARY KEY が無い場合、 NOT NULL カラムだけを持つ最初のUNIQUE インデックス をクラスタインデックスとする• テーブルに PRIMARY KEY も適切な UNIQUE インデックスもない場合は、InnoDB の内部で、行 ID 値を含む合成カラム上に隠しクラスタインデックスが生成される。行 ID は、新しい行が挿入されると単調に増加する 6 バイトのフィールドクラスタインデックス• テーブルに PRIMARY KEY がある場合、それをクラスタインデックスとする• テーブルに PRIMARY KEY が無い場合、 NOT NULL カラムだけを持つ最初のUNIQUE インデックス をクラスタインデックスとする• テーブルに PRIMARY KEY も適切な UNIQUE インデックスもない場合は、InnoDB の内部で、行 ID 値を含む合成カラム上に隠しクラスタインデックスが生成される。行 ID は、新しい行が挿入されると単調に増加する 6 バイトのフィールド
  • 68. class CreateUsersGroups < ActiveRecord::Migrationdef changecreate_table :users_groups, :id => false do | t |t.references :user, :null => falset.references :group, :null => falseendadd_index :users_groups, [:user_id, :group_id], :unique => trueendend多対多
  • 69. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+----------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+----------+----------+-----------+| users_groups | InnoDB | 25000427 | 36 | 1,870.00 | 862.00 | 1,008.00 || users | InnoDB | 9744 | 47 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+----------+----------+-----------+4 rows in set (0.02 sec)多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 70. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+---------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+---------+----------+-----------+| users_groups | InnoDB | 25000579 | 28 | 683.00 | 683.00 | 0.00 || users | InnoDB | 9744 | 47 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+---------+----------+-----------+4 rows in set (0.09 sec)多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 71. 多対多平均行サイズが8バイト減!テーブルサイズが180 MB 減!さらに、インデックスが約1GB減!テーブル全体で約1/3くらいに縮小!どういう計算かは、ともかく・・・
  • 72. インデックスの領域が使われていないので、データサイズの節約。インデックスとデータをBツリーに格納しているので、通常は非クラスタインデックスよりも高速。多対多
  • 73. 試してみるか試さないかはあなた次第
  • 74. ご清聴ありがとうございました。
  • 75. おまけ
  • 76. group_idでのインデックスが、無くなってるので、カバリングインデックスを追加。CREATE INDEX idx_users_groups01 USING BTREE ONusers_groups (group_id, user_id);
  • 77. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+----------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+----------+----------+-----------+| users_groups | InnoDB | 25000427 | 36 | 1,870.00 | 862.00 | 1,008.00 || users | InnoDB | 9744 | 47 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+----------+----------+-----------+4 rows in set (0.02 sec)多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 78. mysql> SELECT-> table_name-> , engine-> , table_rows as tbl_rows-> , avg_row_length as rlen-> , FORMAT((data_length+index_length)/1024/1024, 2) as all(MB) #総容量-> , FORMAT((data_length)/1024/1024, 2) as data(MB) #データ容量-> , FORMAT((index_length)/1024/1024, 2) as index(MB) #インデックス容量-> FROM information_schema.tables-> WHERE table_schema=database()-> ORDER BY (data_length+index_length) DESC;+-------------------+--------+----------+------+---------+----------+-----------+| table_name | engine | tbl_rows | rlen | all(MB) | data(MB) | index(MB) |+-------------------+--------+----------+------+---------+----------+-----------+| users_groups | InnoDB | 25000579 | 28 | 1,008.88| 683.00 | 325.88 || users | InnoDB | 9744 | 47 | 0.44 | 0.44 | 0.00 || groups | InnoDB | 10396 | 44 | 0.44 | 0.44 | 0.00 || schema_migrations | InnoDB | 3 | 5461 | 0.02 | 0.02 | 0.00 |+-------------------+--------+----------+------+---------+----------+-----------+4 rows in set (0.09 sec)多対多平均行サイズデータサイズインデックスサイズ全体のサイズ
  • 79. 多対多平均行サイズが8バイト減!テーブルサイズが180 MB 減!さらに、インデックスが約700MB減!テーブル全体で約2/3以下に!