データベースを使おう

28
データベースを使おう 2013/02/23 UT Startup Gym 1

Upload: shuhei-iitsuka

Post on 08-Dec-2014

7.763 views

Category:

Documents


1 download

DESCRIPTION

UT Startup Gym での講義資料です。

TRANSCRIPT

Page 1: データベースを使おう

データベースを使おう

2013/02/23 UT Startup Gym 1

Page 2: データベースを使おう

UT Startup Gym とは?

アイデアをカタチにするプログラム

2013/02/23 UT Startup Gym 2

l プロジェクト  l 企画から実装まで  l スタートアップ

Page 3: データベースを使おう

スケジュール

2013/02/23 UT Startup Gym 3

Oct,  12 • プログラミング入門

Nov,  12 • プラニング • プロジェクトスタート

Dec,  12 • 開発開始 • 冬季開発合宿

Jan,  13 • ウェブデザイン • 週間報告会

Feb,  13 • jQuery,  中間発表

Mar,  13 • 作業会

Apr,  13 • リリース会

ソーシャルウェブアプリケーション,  API,  bot,  HTML5

Keywords:  

リーンスタートアップ,  ビジネスプラニング,  HTML,  CSS,  PHP,  javascript

チーム結成,  企画,  ディスカッション  git,  フレームワーク,  MySQL,  Apache  

シナリオ,  ペルソナ,  ワイヤフレーム,    サイトマップ,  DB  スキーム  

ゲーミフィケーション,  仮説検証,  データマイニング,  アクセシビリティ  

レスポンシブデザイン,  プレゼンテーション  

Page 4: データベースを使おう

2013/02/23 UT Startup Gym 4

M D 講師(敬称略) タイトル 要素 10 13 飯塚 かんたん Facebook アプリをつくる HTML, CSS, js

  21 飯塚 かんたん Twitter アプリをつくる UNIX, vim, PHP

  27 川上 かんたん アンケートフォームをつくる MySQL, MVC

11 4 AWS 高山様 サーバを立てよう AWS   10 飯塚・石村 スタートアップの心構え ビジネスプラン、リーンスタートアップ   17 飯塚・佐藤 プロダクトデザイン シナリオ、ペルソナ、ワイヤフレーム    24 お休み(飯塚@ジャカルタ)

12 1 ゆーすけべー様 ウェブサービスの企画のコツ 企画プロセス、ウェブサービス運用

  8 飯塚 ウェブから情報をあつめる クローラ, XPath, 正規表現   15 プロジェクトキックオフ アンカンファレンス

  22 飯塚 チームで協力して開発するために git 1 13 飯塚 かんたんキレイなウェブデザイン Twitter Bootstrap, Web Fonts, LESS

  19 石村 ゲーミフィケーション

  26 松尾、川上 中間発表 2 2 未定

  9 ぱろすけさん AV顔画像認識とその周辺 画像認識、機械学習   16 松尾・川上 中間発表会 2 23 飯塚  データベース MySQL

  作業     27   リリース会  

Page 5: データベースを使おう

2013/02/23 UT Startup Gym 5

4/27(土)"UT Startup Gym !リリース会

Page 6: データベースを使おう

今回使うデータ •  データベース: MySQL

–  RDBMS: Relational Database Management System •  SQL という言語でデータの出し入れをするシステム

–  世界で最も普及しているオープンソースデータベース

•  データの中身: 架空の SNS –  ユーザー 約 50 万件 –  会社情報 約 15 万件 –  友人情報 約 1,000 万件

2013/02/23 UT Startup Gym 6

MySQL – Wikipedia http://ja.wikipedia.org/wiki/MySQL

Page 7: データベースを使おう

テーブル設計

user id VARCHAR(128)

name VARCHAR(256) gender_id INT UNSIGNED"

lang VARCHAR(10)"created_at DATETIME"

..."PRIMARY KEY (id)"

2013/02/23 UT Startup Gym 7

friend user_id VARCHAR(128)

friend_id VARCHAR(128) nakayoshi INT

PRIMARY KEY (user_id, friend_id)"UNIQUE KEY (friend_id, user_id)"

company id BIGINT(20) UNSIGNED

name VARCHAR(256) PRIMARY KEY (id)"

Page 8: データベースを使おう

データベースを叩いてみよう •  普通の SELECT 文"

–  SELECT * FROM user LIMIT 10;"–  SELECT * FROM user;"

•  条件指定"–  SELECT * FROM user WHERE id = '109092915251428393573';"–  SELECT * FROM user WHERE name = ‘飯塚修平';"–  SELECT id, name FROM user WHERE created_at >

DATE_SUB(NOW(), INTERVAL 10 MINUTE);"•  同姓同名ランキング"

–  SELECT user.name, COUNT(id) FROM user GROUP BY user.name ORDER BY COUNT(id) DESC LIMIT 10;"

2013/02/23 UT Startup Gym 8

Page 9: データベースを使おう

データベースを叩いてみよう •  従業員数ランキング"

–  SELECT company.id, company.name, COUNT(user_employment.id) FROM user_employment LEFT JOIN company ON user_employment.company_id = company.id GROUP BY company.id ORDER BY COUNT(user_employment.id) DESC LIMIT 10;"

•  Google の従業員一覧"–  SELECT user.id, user.name FROM user LEFT JOIN user_employment ON

user.id = user_employment.user_id LEFT JOIN company ON user_employment.company_id = company.id WHERE company.name = 'Google';"

•  共通の友達"–  SELECT * FROM friend AS f1 LEFT JOIN friend AS f2 ON f1.friend_id =

f2.user_id WHERE f1.user_id = '109092915251428393573' AND f2.friend_id = '113100517422007103669’"

2013/02/23 UT Startup Gym 9

Page 10: データベースを使おう

2013/02/23 UT Startup Gym 10

SQL ムズい・・・ そもそもなんでデータベースを使うの?

Page 11: データベースを使おう

ぶっちゃけファイルでもよい。

2013/02/23 UT Startup Gym 11

ファイルじゃダメなの?

これとか こんなかんじ

もちろんファイルでもOKです。ただ・・・

12年2月13日月曜日

ファイルじゃダメなの?

これとか こんなかんじ

もちろんファイルでもOKです。ただ・・・

12年2月13日月曜日

こんなのとか こんなの

ただ、データベースの利点がある

Page 12: データベースを使おう

データベースの利点 •  SQL言語(かんたん)

–  いちいち入出力書いてたら面倒 –  SQL で統一的に記述できる!

•  とはいえ方言はある (PostgreSQL, sqlite etc.)

•  インデックス(はやい) –  バイナリツリーによる探索速度向上

•  詳しくは後述

•  トランザクション(あんしん) –  処理途中の中途半端な状態を許さない –  複数のクエリをひとつのユニットにまとめる

•  失敗したらロールバック

2013/02/23 UT Startup Gym 12

Page 13: データベースを使おう

インデックス

id name 1 Shuhei  Iitsuka 2 Kazuya  Kawakami ... ... 1468 Taro  Tanaka ... ...

2013/02/23 UT Startup Gym 13

普通に探索すると

SELECT name FROM user WHERE id = 1468;

id = 1468"のやつが見つかるまで探すぜ!

探索時間"O(n)."おそいね

Page 14: データベースを使おう

インデックス

2013/02/23 UT Startup Gym 14

バイナリツリーのインデックスが張られていると

SELECT name FROM user WHERE id = 1468;

探索時間O(log(n))."はやいね

1000

500 1500

250 750 1250 1750

...

2分木探索で"探すぜ!

Page 15: データベースを使おう

2013/02/23 UT Startup Gym 15

データベースつかうといいことは分かったけど、 うちのサービスではどうすればいいの?

Page 16: データベースを使おう

テーブル設計をしてみよう •  たとえばこんな RPG ゲームの戦闘データ

–  どのバトルでどのユーザによってどんな技が繰り出されたか

2013/02/23 UT Startup Gym 16

この形では RDBMS に格納することは出来ない。

battle_id battle_at attack_id attack_name attack_damage player_id player_name battle_type

162 2013/2/22 10:00

2 いあいぎり 30

3 飯塚修平 normal 2 いあいぎり 30

5 ふぶき 80

161 2013/2/22 8:00 1 たいあたり 10

5 川上和也 boss 2 いあいぎり 30

160 2013/2/21 23:00

4 そらをとぶ 40

5 川上和也 normal 4 そらをとぶ 40

8 うたう 0

Page 17: データベースを使おう

正規化 •  1 事実 1 カ所(1 fact in 1 place)を目指して、テーブルの整合性を保ったまま、テーブルの冗長性を排除して、データを効率的に管理できるようにすること – 更新すべき項目の重複を防ぐことができる

•  あんなところやこんなところに「○○」が!

2013/02/23 UT Startup Gym 17

データベースエンジニアへの道 – @IT http://www.atmarkit.co.jp/fdb/rensai/db_enginer03/db_enginer03_1.html

Page 18: データベースを使おう

第1正規形

2013/02/23 UT Startup Gym 18

battle_id battle_at attack_id attack_name attack_damage

162 2013/2/22 10:00 2 いあいぎり 30

162 2013/2/22 10:00 2 いあいぎり 30

162 2013/2/22 10:00 5 ふぶき 80

161 2013/2/22 8:00 1 たいあたり 10

161 2013/2/22 8:00 2 いあいぎり 30

160 2013/2/21 23:00 4 そらをとぶ 40

160 2013/2/21 23:00 4 そらをとぶ 40

160 2013/2/21 23:00 8 うたう 0

battle_id player_id player_name battle_type

162 3 飯塚修平 normal

161 5 川上和也 boss

160 5 川上和也 normal

-­‐  テーブルにキーを設定する -­‐  テーブルの繰り返しグループを別のテーブルに分離する -­‐  導出項目を削除する

battle  attack

player

key:  battle_id

Page 19: データベースを使おう

2013/02/23 UT Startup Gym 19

battle_id battle_at attack_id attack_name attack_damage

162 2013/2/22 10:00 2 いあいぎり 30

162 2013/2/22 10:00 2 いあいぎり 30

162 2013/2/22 10:00 5 ふぶき 80

161 2013/2/22 8:00 1 たいあたり 10

161 2013/2/22 8:00 2 いあいぎり 30

160 2013/2/21 23:00 4 そらをとぶ 40

160 2013/2/21 23:00 4 そらをとぶ 40

160 2013/2/21 23:00 8 うたう 0

battle_id player_id player_name battle_type

162 3 飯塚修平 normal

161 5 川上和也 boss

160 5 川上和也 normal

技名「いあいぎり」を「ばっとうぎり」にしたい!

変更箇所が複数にまたがってしまう!

Page 20: データベースを使おう

第2正規形

UT Startup Gym 20

battle_id battle_at player_id player_name battle_type

162 2013/2/22 10:00 3 飯塚修平 normal

161 2013/2/22 8:00 5 川上和也 boss

160 2013/2/21 23:00 5 川上和也 normal

第1正規形から部分関数従属性を取り除くこと"ex. 「attack_id = 1 」→「たいあたり」

battle_id attack_id num

162 2 2

162 5 1

161 1 1

161 2 1

160 4 2

160 8 1

attack_id attack_name attack_damage

1 たいあたり 10

2 いあいぎり 30

4 そらをとぶ 40

5 ふぶき 80

8 うたう 0

変更箇所が1箇所で済む

Page 21: データベースを使おう

UT Startup Gym 21

battle_id battle_at player_id player_name battle_type

162 2013/2/22 10:00 3 飯塚修平 normal

161 2013/2/22 8:00 5 川上和也 boss

160 2013/2/21 23:00 5 川上和也 normal

battle_id attack_id num

162 2 2

162 5 1

161 1 1

161 2 1

160 4 2

160 8 1

attack_id attack_name attack_damage

1 たいあたり 10

2 いあいぎり 30

4 そらをとぶ 40

5 ふぶき 80

8 うたう 0

まだバトルをしていないプレイヤーが  登録したんだけど・・・  

どこに入れればいいの・・・?

Page 22: データベースを使おう

第3正規形

UT Startup Gym 22

第2正規形から推移関数従属性を取り除くこと"ex. 「battle_id = 162 」→「player_id = 3」→「飯塚修平」

battle_id attack_id num

162 2 2

162 5 1

161 1 1

161 2 1

160 4 2

160 8 1

attack_id attack_name attack_damage

1 たいあたり 10

2 いあいぎり 30

4 そらをとぶ 40

5 ふぶき 80

8 うたう 0

battle_id battle_at player_id battle_type

162 2013/2/22 10:00 3 normal

161 2013/2/22 8:00 5 boss

160 2013/2/21 23:00 5 normal

player_id player_name

3 飯塚修平 5 川上和也

battle player

battle_attack attack

未バトルのプレイヤーを  マスタに追加しておくことができる

Page 23: データベースを使おう

実際に使うときは •  LEFT JOIN でくっつけていく"•  もっとも使われている技名ランキング"

–  SELECT ba.attack_id, SUM(ba.num) FROM battle_attack ba GROUP BY ba.attack_id;"

–  やっぱり技名も欲しい・・・→ LEFT JOIN attack"–  SELECT a.attack_name, SUM(ba.num) FROM battle_attack ba

LEFT JOIN attack a ON ba.attack_id = a.attack_id GROUP BY ba.attack_id;"

2013/02/23 UT Startup Gym 23

Page 24: データベースを使おう

さきほどの例なら •  Google の従業員一覧"•  まず Google が ID = なんちゃらだとして"

–  SELECT user_id FROM user_employment WHERE company_id = なんちゃら;"

•  社名で指定したいので LEFT JOIN company"–  SELECT user_id

FROM user_employment ue LEFT JOIN company c ON ue.company_id = c.id WHERE c.name = 'Google';"

•  さらに従業員の名前を出したいので LEFT JOIN user"–  SELECT u.id, u.name

FROM user_employment ue LEFT JOIN company c ON ue.company_id = c.id LEFT JOIN user u ON ue.user_id = u.id WHERE c.name = 'Google';"

2013/02/23 UT Startup Gym 24

Page 25: データベースを使おう

実際の設計の手順 •  正規化は、冗長なところがないかをチェックするためのもの。

•  設計時はエンティティを考えて、それらの関係を考えていく。 –  エンティティ→マスターテーブル –  関係→トランザクションテーブル

•  たとえば掲示板サイトなら –  マスタ

•  スレッドマスタ •  コメントマスタ •  ユーザマスタ(匿名性なら不要)

–  トランザクション •  投稿テーブル(誰が、どのスレッドに、なんというコメントをしたか)

2013/02/23 UT Startup Gym 25

Page 26: データベースを使おう

2013/02/23 UT Startup Gym 26

Page 27: データベースを使おう

チューニング •  高速にデータを取得するためにインデックスを張る、SQL を書き換えるなどの工夫をする。

•  EXPLAIN コマンド –  詳細は http://nippondanji.blogspot.jp/2009/03/mysqlexplain.html

•  サブクエリは使わない –  詳細は http://nippondanji.blogspot.jp/2009/03/mysql_25.html

2013/02/23 UT Startup Gym 27

Page 28: データベースを使おう

参考文献 •  データベースを使おう @UT Startup Gym by @amachang

http://www.slideshare.net/tushuhei/ss-16506218 •  第3回 素早く正規形を見抜く実践テクニック – @IT

http://www.atmarkit.co.jp/fdb/rensai/db_enginer03/db_enginer03_1.html •  MySQLのEXPLAINを徹底解説!! – 漢のコンピュータ道

http://nippondanji.blogspot.jp/2009/03/mysqlexplain.html •  なぜMySQLのサブクエリは遅いのか。 – 漢のコンピュータ道

http://nippondanji.blogspot.jp/2009/03/mysql_25.html

2013/02/23 UT Startup Gym 28