2ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

DB設計を語るスレ 3

1 :NAME IS NULL:2010/03/26(金) 15:39:21 ID:WShq9Pbx
引き続き語れ!!

前スレ
DB設計を語るスレ 2
http://pc11.2ch.net/test/read.cgi/db/1223458453/

過去スレ
DB設計を語るスレ
http://pc11.2ch.net/test/read.cgi/db/1166540159/

2 :NAME IS NULL:2010/04/07(水) 09:27:33 ID:???
またサロゲート厨か

3 :NAME IS NULL:2010/04/14(水) 19:34:41 ID:???
T字形ERマスターの俺様が華麗に2ゲット!

4 :NAME IS NULL:2010/04/17(土) 02:43:18 ID:???
有給と勤怠の管理システム作ってるけど、
有給の設計むずいな。前年度の繰越とか

5 :NAME IS NULL:2010/04/17(土) 18:26:32 ID:???
社員 今年残 前年残
A     20   15
B     5    9

で消化するとき今年残から先に減らせばいいだけ
繰越は単に今年残→前年残、今年残→規定リストからセットで済む

6 :NAME IS NULL:2010/04/18(日) 17:34:12 ID:???
なにそのくそせっけい

7 :NAME IS NULL:2010/04/18(日) 22:26:32 ID:???
どうしろと

8 :NAME IS NULL:2010/04/21(水) 00:38:45 ID:GuWbcNTa
簡単なのでいいから勤怠管理の設計載ってるサイト教えて下さい

9 :NAME IS NULL:2010/04/21(水) 14:58:34 ID:???
俺だったら、年次ごとに与えられた日数と消化した日数は別々に保存する。
計算結果だけ保存するのは、俺の感が駄目だと言ってる。

10 :NAME IS NULL:2010/04/22(木) 03:22:06 ID:???
有給テーブル
取得日
日数

勤怠テーブル
日付
出勤時間
退社時間
勤怠区分

勤怠区分テーブル
勤怠区分

有休残計算はストアドとかで

11 :NAME IS NULL:2010/04/30(金) 13:54:02 ID:???
T字型マスターの俺様、なんとか言ってやってください!

12 :NAME IS NULL:2010/05/04(火) 21:11:32 ID:???
自分達に無い物を作ろうとするから、どう設計すれば良いのか見えないんじゃね?


13 :NAME IS NULL:2010/05/06(木) 17:59:31 ID:???
有休テーブル
+社員ID
+年次(っぽいもの)
+付与日数

有休実績テーブル
+社員ID
+年次(っぽいもの)
+消化日数

有休実績テーブル(案2)
+社員ID
+取得開始年月日
+取得終了年月日

今現在の有休残はストアドとかで

14 :NAME IS NULL:2010/05/06(木) 23:53:16 ID:???
>>13
有給実績テーブルの消化日数って、有給テーブルにくっつけたらダメなの?なんでわけてんの?

15 :NAME IS NULL:2010/05/07(金) 00:51:45 ID:???
13じゃないのに勝手に答えるけど、
それだと付与・消化の属性を追加して使い分けるとか
あるいはrowそのものを書き換える必要が出てくるじゃない

テーブルで分けといた方が分かりやすいと思うな
休んだ日数を細切れでブっこんでおいて、全体の消化日数はID&年次でselectしてsum取ればいいし

16 :NAME IS NULL:2010/05/07(金) 10:15:44 ID:???
>>14
有給の付与が年度の開始時にしか起こらないって脳内ルールを作ってないか?

17 :NAME IS NULL:2010/05/07(金) 12:14:53 ID:???
つまりそれは回りまわって>>12に帰結するわけだな(涙

18 :NAME IS NULL:2010/05/07(金) 20:15:10 ID:???
有効期限があるポイントを管理しなきゃならんのだわ。
やっぱり1ポイント1レコードかしら?

それとも「何月何日に100ポイント取得」「何月何日に30ポイント消費」みたいな、
ログ記録かしら。

教えてちょんまげ。

19 :NAME IS NULL:2010/05/07(金) 21:11:50 ID:???
直したのかよ
有給ないやつにも分かるように直したのかよ

20 :NAME IS NULL:2010/05/08(土) 06:31:21 ID:???
>>16
有給は半年前倒しで全社員一斉に与えても
いいんだよ。でなければ、入社日から計算。
入社半年で、0.5年度。一年半で1.5年度。
年度は入社何年目かって事でしょ。西暦
じゃないよ。この年度単位でないと、
繰越計算しにくいと思う。だから、年度に
与えた日数と消化した日数持たせていい。

>>15
なんかいまいちその利点がイメージできない。消化日数を持たせた時点で、集計
してrowをその都度更新していくのは
当たり前だし。それに、本当にsumなんか
で繰越の計算できんの?

21 :13:2010/05/10(月) 11:33:11 ID:???
実際に消化した実績日数だけで良いシステムなら、同一テーブルでもいいけど、
大抵は、事前に申請が必要だし、その申請こみで今現在の残日数を求める必要が
あったりする。つまり、大抵は(案2)みたいなテーブルが必要になるだろうってこと。

22 :NAME IS NULL:2010/05/17(月) 23:44:56 ID:???
そういえば最近は時間単位で年休取得できる会社もあるよな。

23 :NAME IS NULL:2010/05/18(火) 00:21:58 ID:???
時間単位はややこしい。日単位なら
その日の勤怠区分で処理できるのに。
例えば、10時出勤でも遅刻でないとか、
しかし、そのその日の勤務時間は一時間
マイナスで、有給で一時間補充とか、考えるだけで鬱になる

24 :NAME IS NULL:2010/06/15(火) 00:30:24 ID:???
簡単相互リンク集みたいなのを作ってまして
初めてDBをまともに使うのですが、こんな設計で問題ないでしょうか?

仕組みとしては、
・ひとつのUserIDに複数のサイトを登録可能
・申請が承認されると表示される
・相手にはUserIDは秘匿。

UserTable
---------------------
UserID | Mail         |  Password   | 自分のSiteIDs     | 承認待ち              | 申請中
---------------------
u2145  | test@gmail.com  |   1234     | s3265,s2664,       | s3526(相手) to s3265(自分),   | s3265(自分) to s4377(相手)


SiteTable
---------------------
SiteID | UserID | URL         | Title    | ビットフラグ        | ジャンル     | 紹介文       | リンクしているSiteIDs
---------------------
s3265 | u2145 | http://google.com/ | Google  | 未認証,リンク切れ,etc   | 検索/リンク集 | 検索サイトです。 | s6325,s2355,s2362,s2355,


(未認証は、本人のサイトか未確認の意味。仮登録後、数時間未認証の場合テーブルから削除します。別のテーブル作ったほうがいいのかな)

リンク集生成時にURLとタイトルを取得する為に複数のSiteIDを問い合わせるので、心配なのですが
普段はHTMLファイルを生成して追加/削除するときにHTMLファイルを更新する感じにすれば問題ないでしょうか?
アドバイスよろしくお願いします。

25 :NAME IS NULL:2010/06/15(火) 01:58:11 ID:???
>>24
ユーザー毎にテーブル作った方がいい

26 :NAME IS NULL:2010/06/15(火) 06:01:44 ID:???
to に笑った

27 :NAME IS NULL:2010/06/15(火) 06:15:29 ID:???
「s3265,s2664」とかなってるのはカラムの中にカンマ区切りにするって意味?
そんなんDB使う意味ないぞ。テキストデータで持ってた方がマシなレベル。
それに静的データ(マスタ)と動的ステータスは完全に分けた方がいいがごっちゃになってる
それと未認証とリンク切れとか意味が全く違うものを一緒にしちゃいかん。

>>25
ユーザが増えたらcreate table発行か?ありえん。

28 :24:2010/06/15(火) 06:42:19 ID:???
レスありがとうこざいます。


>>27

カンマ区切りでした。。SQL側でひとつのカラムに複数の値を管理できるのでしょうか?
よければヒントの検索ワード教えてもらえませんかTT
(カラムにレヒードを追加できるのでしょうか!?)

ビットフラグでカラム減らそうとしてました。
素直にtrue/falseでそれぞれカラムあったほうがいいんでしょうか?

静的と動的はこの場合、頻繁に書き換わるSiteIDが動的?ですかね
UserTableの申請中などの情報は新しいテーブルに作ってみます。



29 :NAME IS NULL:2010/06/15(火) 07:01:33 ID:???
>カラムに複数の値を管理
配列を入れられるDBもあるけど検索に使いづらくなるのでまずやらない。
そういう場合、RDBは複数レコードで管理する。もちろん行数は多くなるが管理や検索速度のバランスだからしゃーない。

んで、テーブルだが、ちょっと要件いまいちわかってなくて考察適当だがこんな感じだと思うぞ。
UserMasterTable (UserID(PK)|Mail|Password)
SiteMasterTable (SiteID(PK)|サイトのUserID|URL|ジャンル|紹介文|リンク切れフラグ|未認証フラグ)
SiteLinkStatusTable (リンク元SiteID(PK)|リンク先SiteID(PK)|ステータス(未承認/承認済/削除)|更新日時)

SiteLinkStatusTableは申請時1レコード、承認されて相互リンクになると2レコードになる。
未認証→認証を行うのは管理者でいいの?

30 :NAME IS NULL:2010/06/15(火) 07:19:50 ID:???
>>29
すごく具体的ありがとうこざいます> <

なるほど、こんなテーブルになるのですか!
素人考えで一つのテーブルに纏めすぎてたんですね ; ;

認証は管理者ですね。リンク切れは定期的に確認する感じです。

ちょっと私には複雑すぎてSQL質疑応答スレで聞くことになると思いますが
とりあえず寝てから作成してみます。


31 :NAME IS NULL:2010/06/15(火) 16:32:38 ID:???
未認証とリンク切れは一緒でいいんじゃまいか
認証されてなければリンク切れとは判定しないだろうし
0 = 正常 / 1 = 未認証 / 2 = リンク切れ
とでもすれば

32 :NAME IS NULL:2010/06/15(火) 17:42:05 ID:???
まあ、なんにせよ要件次第ではあるが

>>29
>仮登録後、数時間未認証の場合テーブルから削除します
なので、サイトマスターに最低限、申請(仮登録)日時いるだろうな
そうなると本登録日とか、ほかにも項目ほしくなるだろうけど

>>31
・未認証で承認しようとしたらリンクが切れてました
・承認してたんだけど、ある日リンクが切れました
の二つを区別して記録したいなら分けておかないとだめじゃね
もしくは別途サイト登録履歴みたいなテーブルもたせるか

33 :24:2010/06/15(火) 18:22:47 ID:???
皆様ありがとうこざいます

作ろうとしてるのは、ユーザーのサイトにphpファイル(名前と設置場所固定)を設置させて被リンク効果を出す感じなのですが
phpファイル自体は、
$SiteID = 235455;
$fp = fopen("ttp://www.mydomain.com/site/$SiteID.html", "rb") or die ("Cannot open");
fpassthru($fp);
こんな感じでURLを取得して表示してるだけです。

後出しなのですが
未認証は、phpファイルが設置されていない状態で
リンク切れは、トップページからそのphpファイルにリンクされてない状態です。
相互リンク中に未認証/リンク切れになった場合は、一定時間後にSiteLinkStatusTableからサイト事消す感じになります。

そして後から気づいたのですが、リンク申請にメッセージを添えられる予定だったので
新たにMessageBoxTableを作ってみました。(メッセージボックスはユーザーが自由に消去できる予定)

UserMasterTable (UserID(PK)|Mail|Password|メールを受け取るか)
SiteMasterTable (SiteID(PK)|サイトのUserID|URL|タイトル|紹介文|ジャンル|ページランク|バックリンク|ステータス(未認証/リンク切れ/正常)|ステータスが変わった日時)
SiteLinkStatusTable (リンク元SiteID(PK)|リンク先SiteID(PK)|更新日時)
MessageBoxTable ( ユニークID(PK) | 差出人SiteID | 宛先SiteID | タイトル | 本文 | フラグ(リンク申請/リンク不成立/削除報告) | 日時 )

UserIDとSiteIDは登録時間のUNIXタイムスタンプを使おうかと思ってます。

34 :NAME IS NULL:2010/06/15(火) 19:08:29 ID:???
UNIXタイムスタンプはダメだ
DATETIME型でカラム作った方がいいぞ


35 :NAME IS NULL:2010/06/15(火) 20:37:55 ID:NSd5kCf1
在庫調査のDBを作ろうとしてるのですが、
差分データのようにしないとデータ多すぎて一ヶ月もしないうちに大変な事になってしまいそうです。
エリア、店名、商品名、価格、個数、調査時間
最低限保持しないといけないのが上記項目で
同じ店でも同じ商品名でも陳列が別なら別登録になります。(ヤフオクで同じ商品が同じ価格でずらっと並んでるような)
調査1回につき、20〜30エリア、1〜100店、商品1〜100点、個数1〜100程度になるので単純にDBに登録すると1回で最大時30万行になってしまいます。
これを3時間ごとに調査となると、1ヶ月で数千万行になってしまって現実的ではありません。
なので調査ごとの変化は1割にも満たないので差分の登録の仕方や利用の仕方を勉強したいのですが、
そのような設計例の載ってる本やサイトをご存知ないでしょうか?

36 :NAME IS NULL:2010/06/15(火) 21:05:10 ID:???
差分ってか
ようは在庫変動のトランザクションを持ってりゃいいだけの
話のように思うが

37 :NAME IS NULL:2010/06/15(火) 21:52:45 ID:NSd5kCf1
すいませんもう少し詳しく教えていただけませんか?
単に今の在庫がわかればいいってわけではなくて、
調査日のその時間にどこにどんな値段で在庫がいくらかあったか、店自体開いてたか開いてなかったかなどの
そのままの情報を保持したいので、
在庫変動したら値を変えるだけってわけではないのですが、そういう意味でもしおっしゃられていたのならすみません。

38 :NAME IS NULL:2010/06/15(火) 22:16:17 ID:???
もし本当にそのままの情報を保持する必要があるなら
30万件だろうがそのまま持っとくほうがいいだろう
ただし、それを保存している間に在庫が動く可能性があるから
その瞬間の在庫という一貫性は保てないぞ

ただし、たとえば保存期間を三日とかにしておく等の制限をつける

三時間おきのデータを数年も保持しとかないといけないとかいうなら
要件を見直すべきかと

39 :NAME IS NULL:2010/06/15(火) 22:32:03 ID:???
取ったデータで何をするかじゃないかな。
例えばWeb画面でセミリアルタイムで変動をグラフで見せたい(計算させたい)のだったら1クリック5時間のクソアプリになるが、
月に1回バッチで在庫変動情報の帳票を作りたいだけなら全部突っ込んで1億レコードになっても何ら問題ない。

40 :NAME IS NULL:2010/06/15(火) 22:35:20 ID:???
>>33
てか「(申請に添える)メッセージ」が「(サイト間の)リンク申請情報」を持ってるっておかしくなってるじゃん。

41 :24:2010/06/15(火) 23:25:43 ID:???
>>40
おかしいですか?
SiteLinkStatusTableにメッセージを置くのもおかしいので
MessageBoxTableにリンク申請情報を持たせてしまえば楽かなぁと
(メッセージ消したらリンク拒否みたいに)


42 :NAME IS NULL:2010/06/16(水) 01:34:09 ID:???
UserID MEDIUMINT NOT NULL AUTO_INCREMENT
SiteID MEDIUMINT NOT NULL AUTO_INCREMENT


43 :NAME IS NULL:2010/06/16(水) 10:58:42 ID:1LUS1Pf+
>>38
要件見直すことにします。
>>39
そのクソアプリに近い感じなのでリアルタイムなものと、日間月間変動情報なものとわけて考えて見ます。

44 :NAME IS NULL:2010/06/18(金) 18:45:41 ID:???
これ見てよ↓
http://livedoor.blogimg.jp/tekepo/imgs/3/4/3414dfca.jpg
ばらまこうぜ!


45 :NAME IS NULL:2010/06/26(土) 08:48:25 ID:HzXxnfag
最近DBの勉強をし始めたのですが
通し番号 社員ID 社員名 製品ID 製品名 登録日時
のような列があった場合、通し番号 社員ID 製品ID 登録日時のテーブルと他2つに正規化できますが、
検索するときに必ず名を利用する場合(社員名、製品名、登録日時を取り出すのがメインの利用方法)、
サブクエリが増える分検索が遅くなると思うのですが
こういった場合でもテーブルって分けるべきなんでしょうか?
社員ID、製品IDを利用する事はほとんどありません。
正規化するとDB容量は節約できますが、利用時の負荷が増大するのでデメリットに感じます。
それともサブクエリ増えてたとしても、列が少なくDB容量が小さくなるようにした方が速くなるでしょうか?

46 :NAME IS NULL:2010/06/26(土) 09:23:29 ID:Y5TEab6Q
やってみないと判らないと言われればそれまでだけど、

そんなに心配しないとイケないほど検索が遅くなる?負荷が増える?


47 :NAME IS NULL:2010/06/26(土) 09:52:42 ID:???
初心者なら型通りにやれ。
パフォーマンスを気にするなら、テーブル設計に手を入れるのはSQLチューニングで
改善の余地があるかどうか自分で判断できるようになってからだ。

48 :NAME IS NULL:2010/06/26(土) 10:06:21 ID:???
>>45
パフォーマンスのための非正規化なんてのは最後の最後の最後の手段。
社員数が1000万〜1億人もいるならそれもありかもなー、なレベル。
考えるのがムダとはいわないが、悩むのはムダ。

49 :NAME IS NULL:2010/06/26(土) 10:12:29 ID:HzXxnfag
最終手段なんですね・・・
まずは基本どおりの設計を覚えて経験していくことにします。ありがとうございました。


50 :NAME IS NULL:2010/07/02(金) 08:29:18 ID:???
>>48
プロフを参照したところこの方、銀歯を作る仕事(プッ)をなさっていたそうで(苦笑)
道理で、物作りの厳しさ、商売の難しさどれを取っても何一つ理解しておらず、突っ込み所満載なわけです
しかも過去形である所を見ると景気に関係なく黙ってても患者が来る、
病気や虫歯を直す商売でさえ勤まらなかったということでは(笑)
銀歯と金型では要求される精度も品質もまるで違います
質問者が何を作りたいのかが明らかにされていないため分かりませんが
趣味のようなもの、とおっしゃるなら趣味の掲示板で相談されたらいかがでしょうか
その分野の同好の士が良い方法をご存じかもしれませんから
もちろん、趣味の世界といえども技術は只で教えてもらえるほど甘い物じゃないという事をお忘れなく

51 :NAME IS NULL:2010/07/02(金) 12:07:01 ID:???
どこの誤爆?妙に番号だけあってて笑える。

52 :NAME IS NULL:2010/07/03(土) 11:43:06 ID:magiIcce
enumを使うか、マスタ化するかについて。
http://www.developer0000.jp/2008/11/08/3163/
http://blogs.wankuma.com/ognac/archive/2009/09/07/180928.aspx

全部をマスタ化すると無駄な感じがするのは確かだけど、
表示順や表示名、ロジック分岐フラグなどのパラメータをもてる。
マスタ化しておくことでアプリ内のswitch文を減らすことができる場合
も多々あるので、基本的にはマスタ化が好きなんだけどどう思う?

53 :NAME IS NULL:2010/07/08(木) 04:33:44 ID:mgDV/kGB
英語⇔日本語
みたいな対応表を作る時のようにどちらも主キーになるような場合は
どちらかを主キーにしてもう片方もインデックスする感じになるんでしょうか?

54 :NAME IS NULL:2010/07/08(木) 05:47:39 ID:???
別の連番のキーをつけた方がいいんじゃない?

55 :NAME IS NULL:2010/07/08(木) 16:50:07 ID:mgDV/kGB
>>54
ID 日本語 英語で全部ユニークインデックスってことですか?
IDは使う予定ないのですが将来に備えてということでしょうか。

56 :NAME IS NULL:2010/07/08(木) 17:37:37 ID:???
日本語と英語はユニークである必要無いんじゃない?
確実に1対1なの?

57 :NAME IS NULL:2010/07/08(木) 18:05:55 ID:mgDV/kGB
>>56
確実に1対1です。かぶることはありません。
商品名の日本語⇔英語⇔中国語⇔ドイツ語とあるとして
日本語から英語、ドイツ語から中国語みたいに検索したいんです。

58 :NAME IS NULL:2010/07/08(木) 18:36:57 ID:???
かぶらないって空欄も無いってことか
でも連番のidあったほうがいい気がするなあ
検索対象の項目はそれぞれインデックス作ればいいし

59 :NAME IS NULL:2010/07/08(木) 19:50:03 ID:???
create table Locale(
LocaleID int,
Language char(3),
Message nvarchar(100)
)
select jpn.Message, eng.Message
from Locale as jpn
inner join Locale as eng
on jpn.LocaleID = eng.LocaleID
and eng.Language = 'eng'
and jpn.Language = 'jpn'



60 :NAME IS NULL:2010/07/08(木) 19:57:54 ID:???
商品名の対訳表なら、商品の主キー+言語コードで主キーにするな、俺なら


61 :NAME IS NULL:2010/07/08(木) 20:48:47 ID:mgDV/kGB
>>59 >>60
なるほど。これなら言語増えても列増やさなくて済むんですね。
こういうの自己結合って言うんですね。
自己結合って知らなかったので調べてみます。
いま全く知らない状態だと select Message, Language from Locale where LocaleID = 3
の方が速いんじゃないの?とか
行数増えると結合してるから遅くなるんじゃないの?とか思ってたりします。

62 :NAME IS NULL:2010/07/08(木) 21:24:44 ID:???
自己結合知らんような初心者がパフォーマンス考えるとかムダだから

63 :NAME IS NULL:2010/07/08(木) 23:34:03 ID:mgDV/kGB
>>62
はい。ベテランの方々が提示したものが初心者の私が考えるより確実にいい設計だと思うので、
そのまま使おうと思います。

64 :NAME IS NULL:2010/07/09(金) 00:55:58 ID:???
create table locale (
localeid int,
jpn nvarchar(100),
eng nvarchar(100),
doitu nvarchar(100),
china nvarchar(100)
)

65 :NAME IS NULL:2010/07/09(金) 01:07:19 ID:???

メンテしやすい

66 :NAME IS NULL:2010/07/09(金) 01:15:13 ID:???
それはないわ

67 :NAME IS NULL:2010/07/09(金) 01:27:27 ID:???
俺はその形大好きだがw

68 :NAME IS NULL:2010/07/09(金) 01:38:57 ID:???
>>66
なんでないと思うのかな。必ず全部の言語のデータを一対一で作るという前提なら、ありだろ。

69 :NAME IS NULL:2010/07/09(金) 03:42:13 ID:???
だってdoituだよ?

70 :NAME IS NULL:2010/07/09(金) 11:37:32 ID:???
>>66
将来にわたって言語の追加変更削除がないことが担保されるならありだと思うが

71 :NAME IS NULL:2010/07/10(土) 00:23:34 ID:???
add columnしとけ。

72 :名無しさん@そうだ選挙に行こう:2010/07/10(土) 10:24:04 ID:???
>>64
要件変更時に悲惨なことになりそうな予感しかしない。

73 :名無しさん@そうだ選挙に行こう:2010/07/11(日) 10:24:03 ID:???
chinaだけちゃんとしたフルネーム

74 :名無しさん@そうだ選挙に行こう:2010/07/11(日) 10:25:47 ID:???
あ、フルネームって前に付くあれは無しで

75 :NAME IS NULL:2010/07/12(月) 22:21:49 ID:???
ごく基本的なテーブル設計の話なんですが。

例えば「プレイヤーは複数の村を所持、村は複数の家を所持する」場合って

こういうのが↓依存リレーションで
playerテーブル:primary(player_id), player_name, ...
villageテーブル:primary(player_id, villege_no), village_name, ...
houseテーブル:primary(player_id, villege_no, house_no), house_name, ...

こういうのが↓非依存リレーションって言うんですよね?
playerテーブル:player_id(primary), player_name, ...
villageテーブル:village_id(primary), player_id(foreign), village_name, ...
houseテーブル:house_id(primary), village_id(foreign), house_name, ...

どちらを採択すべきか、っていうのは何を基準に考えたらいいんでしょう?
(もしくはどちらでもない別のがあるとか)
雑談程度に前者の設計について話してたら「20年前の設計だろ」なんて言われてしまって
ちょっと気になっています。(その人は言い捨てて消えてしまったので聞けない)

またそれぞれのメリットデメリットなんかもあれば教えて頂きたい
(もしくは参考URLでも)。わりと調べたつもりなんですがイマイチいいのがHitせず。

76 :NAME IS NULL:2010/07/12(月) 22:27:59 ID:???
実際に両方で作ってみたらいいじゃん。
どっちもhouse_name village_nameを何度も書くはめになることに気づくよ。

それでもいいんだ!っていうなら1テーブルで作っちゃえばいいと思う。
「いちいち」player village houseを分ける必要ないでしょ。

77 :75:2010/07/12(月) 22:29:29 ID:???
あ、各テーブルの関係は1:Nです。情報後出しで申し訳ない。

あと設計のケースとして一個忘れてた、
player, player_villege, villege, villege_house, house と作るケース。
なんて呼ぶのかわかりませんが。

一応自分の考えを書いておくと、
1:Nで、それこそ子の存在が親の存在に依存する場合は依存リレーション、そうでなきゃ非依存
ってだけの話かと考えているのですが。古いとかじゃなくて。

↑に追加で書いたのは、N:Nのときに使う、と。
(逆に言うと1:Nのときに使うメリットは特に無いと思う)

78 :NAME IS NULL:2010/07/12(月) 22:32:53 ID:???
ごめん見落としていた。
>>75の後者って、一つの村は一つのユーザしか所有できないという制限になると思うけど
それはそういう仕様?
ならそれでもいい。

前者は正規化すべき対象がある(かつ、それが煩雑になりすぎない)のに
やらないというところが20年前なんじゃないかな。

79 :75:2010/07/12(月) 22:45:14 ID:???
>>78
そこは(遅れましたが)1:Nなので仕様です。

前者のほうが、「家IDから所有プレイヤーを逆引きするのが楽」だとか、
「親が存在しないのに子が存在しうる」といったデメリットがありますが
それでも後者にすべき?

今挙げた二つのデメリットは、最悪冗長なカラムを持つとか、
制約をしっかり設定すればいい話だけど…
パフォーマンスとしては前者の方がいいような気がするのですが。

…いや、それこそ両方組んで実データぶっこんでテストしなきゃわからないか。
結局どちらが是かは要件次第、なのかなぁ。

80 :NAME IS NULL:2010/07/12(月) 23:07:09 ID:???
1:Nなら前者にする必要がないんじゃ?
> villageテーブル:primary(player_id, villege_no), village_name, ...
に、unique(village_no)をつけて1:Nであるとアピールしてもいいけど。

「親が存在しないのに子が存在しうる」
これを避けたいなら外部キー制約でいけると思う。

パフォーマンスはこの情報だけだと環境によるとしかいえないかと。

あと、誰も所有していない村や家はどうなるの?

81 :75:2010/07/12(月) 23:25:03 ID:???
あれ、俺疲れてんのかな…

よく考えたら子があるのに親がないリスクは前者も後者も同じですよね。
とにかくこれは制約でどうにでもなると。

誰も所有してない村や家は存在してはいけないので削除…いや、
件数がかなり多い(数千万レベル)のでdelete_flag式にするから制約できないや。
そこはPGの責任でしっかり組むことにします。

やっぱり前者に拘る理由は「逆引きが楽」くらい?
indexによる検索性能…も正しくIndex作れば同じ?か?
だんだん「そもそも依存リレーションの存在価値って何」って考えになってきた。

ちなみに質問では親ー子ー孫の3層にしましたが実装は4層。
前者にするとキー長が長くなって検索にはむしろ不利なのか?

82 :NAME IS NULL:2010/07/12(月) 23:35:48 ID:???
後者は外部キー制約あるんだから、家があるなら村はあるはずだし、
村があるならプレイヤーはいるはずになっているよ。

キーが長くなるというか、インデックスが肥大化するんでないかね。
そのへん詳しくないけど。

依存リレーションという言葉も知らなくてなんだかごめん。

83 :NAME IS NULL:2010/07/12(月) 23:42:05 ID:???
で、今依存、非依存について調べたわけですが、

前者は存在しないplayer_idをvillageに登録できるし、
villageがなくともplayerを登録できるので、互いに非依存

後者は>>82で書いたように、playerがいなければvillageに
登録できないが、villageがなくともplayerは登録できるため、
villageはplayerに依存し、playerはvillageに非依存である

ということなんじゃないのかなーと。

84 :NAME IS NULL:2010/07/13(火) 00:03:57 ID:???
PG的には村や家に確実にユニークなIDが振られてる方が楽だと思うが。逆引きするにしても。
「前者のvillege_noやhouse_noも実はユニークなんです(キリッ」なら糞設計と呼ばれても仕方ないと思うけど。

85 :NAME IS NULL:2010/07/13(火) 00:16:17 ID:???
どう考えても後者の設計だな。前者のが古いかどうかは知らないが、親子関係が変更になった時に主キーに触らないといけないのが気持ち悪い。

86 :75:2010/07/13(火) 00:47:25 ID:???
うーむ…。よし、ここは経験と思って、後者で実装することにします。
すでに前者で組んでる最中の、取り返しが付かない段階のシステムがあるので、
違いを肌で感じることにします。

ありがとう御座いました。肌で感じたあとブログにでもまとめようと思います。

87 :NAME IS NULL:2010/07/13(火) 00:52:30 ID:???
てかもっと新しい(?)というか安全なのは、「プレイヤー-村」関連テーブルと「村-家」関連テーブルを別途作ることじゃないかね。

88 :75:2010/07/13(火) 00:58:41 ID:???
>>87
それが>>77で追加したやつのことなんですけど、
N:Nならそうせざるを得ないとして、
1:Nでもそこまでします?

その形にすると、子要素1件の増減につき必ず2テーブル触らないといけないので
パフォーマンスが気になります。

1:Nなので、「プレイヤー村」関連テーブルと「村」テーブルの
件数って完全一致で、「なんのために2テーブルに別れてんだ?」って考えてしまうのですが。

89 :NAME IS NULL:2010/07/13(火) 01:16:13 ID:???
その程度でパフォーマンスが気になるほど更新が頻繁なのか?

90 :75:2010/07/13(火) 01:30:31 ID:???
更新はそれなりに頻繁、件数が億単位を想定。
パフォーマンスのために多少の開発効率を落とすのも辞さないレベル。

91 :NAME IS NULL:2010/07/13(火) 01:34:22 ID:???
んな条件を後出しすんじゃねぇよwww
億単位レコードのテーブルは非正規化されてる方が普通なくらいだろw

92 :75:2010/07/13(火) 01:41:34 ID:???
で、ですよね。すいません。

それを先に出すべきとか言うところに頭がピンと来ない人間が
億単位システムのDB設計をしているという…。

93 :NAME IS NULL:2010/07/13(火) 01:43:50 ID:???
ていうかそれ何のDB?

94 :75:2010/07/13(火) 01:53:46 ID:???
MySQLです。

まぁ最初はよほど負荷が見えてるところ意外は基本的に正規形で考えて
後から発覚した負荷について非正規形にする感じで考えてる。

95 :NAME IS NULL:2010/07/13(火) 02:29:42 ID:???
それがもしモバゲとかグリーとかブラゲならDB以外にも抑えておかないといけない点がいくつかあるんだけど
その辺は大丈夫なのかね。

96 :75:2010/07/13(火) 02:37:20 ID:???
そのへんは肯定も否定もしないでおくけど
memcache使うとか基幹システムAPIは極力叩かないとかは抑えてるつもり。
まぁスレ違いにもなって申し訳ないのであくまでDB設計の話を、と。
ご忠告感謝。


97 :NAME IS NULL:2010/07/13(火) 02:46:23 ID:???
そっか。それなら、だいじょうぶかな。DBも分散を検討してね。
うまく行くことを願っているよ。

98 :75:2010/07/13(火) 03:59:17 ID:???
MASTER、SLAVEの分散もありました、忘れてました。
あとコネクションを極力短く、少なくとか。状況次第じゃいったん切るとか。

で、報告までに。
「複合キー」とか「サロゲートキー」とかでググりまくったら、
「古い」なんて言われたのもぼんやりと納得できてきました。

階層構造に複合キーを使うなんてのは2秒で否定されるレベル、
といった感じが伝わってきました。
(それでも「必ずしも」ではない、ケースバイケースなんだろうけど)

取り返しがつく今のうちに修正に入ることにします…。

99 :NAME IS NULL:2010/07/13(火) 10:25:55 ID:???
今どき複合キーはないわ。
オブジェクト指向とかORM(Object Relational Mapping)とか考えるとサロゲートキー一択っしょ。

あと、1:Nなら関連テーブルは不要だね。

100 :NAME IS NULL:2010/07/13(火) 11:55:11 ID:???
俺なら前者にはしない。
なぜなら、playerが所有しない村も(今は無くとも)存在するだろう(かもしれない)し、家も同様。
また、所有者が変更になるとき、pkeyの更新になるのはいただけない。

101 :NAME IS NULL:2010/07/13(火) 22:17:58 ID:???
複合キーとサロゲートキーって、
具体的にどう違うの?


102 :NAME IS NULL:2010/07/13(火) 23:08:29 ID:???
サロゲートは完全なキーであるためだけのキー。


103 :NAME IS NULL:2010/07/14(水) 13:04:15 ID:???
>>102
単独か複合かは関係ないんですね?
ユニークと同じ意味と思っていい?


104 :NAME IS NULL:2010/07/14(水) 13:13:29 ID:???
>>103
何で調べないの?
Wikipediaでもある程度わかるのに。
http://ja.wikipedia.org/wiki/%E4%B8%BB%E3%82%AD%E3%83%BC

105 :NAME IS NULL:2010/07/14(水) 22:43:21 ID:???
サロゲートキーは「本当はいらないはずだけど、どうしても作らなければいけない」
というイメージがあります。
ダミー列がprimary keyのような感じ。

106 :NAME IS NULL:2010/07/14(水) 22:52:25 ID:???
祇園精舎の鐘の声
諸行無常の響きあり

沙羅双樹の花の色
盛者必衰の理をあらわす

おごれる人も久しからず
ただ春の世の夢のごとし

たけき者も遂には滅びぬ
偏に風の前の塵に同じ

サロゲートキー、それは自然キーの否定。


107 :NAME IS NULL:2010/07/15(木) 09:22:23 ID:???
>>105
あんたの感想はわかった。それで?

108 :NAME IS NULL:2010/07/15(木) 11:02:19 ID:???
いやまぁ合ってるよ
業務要件上はいらないけど、システム要件上は必要なので
ダミー(ユニークネスを保証する以外に意味のない)列を追加するわけだから

109 :NAME IS NULL:2010/07/15(木) 11:14:09 ID:???
まーた始まった

110 :NAME IS NULL:2010/07/15(木) 21:21:24 ID:???
>>107
ごめんなさい。

111 :NAME IS NULL:2010/07/18(日) 09:49:29 ID:???
>>109
ん?まーた始まったって?

私は初めて書き込みますが、サロゲートキーは一つのデータベースで必要な部分と不必要な部分があります
必要な部分では必ず適用します
不要な部分では使用しません
何故必要な部分で使用するかというと使用しなかった時に大変困ったという経験則に基づくものです
不要な部分というのはデータベースごとで違うでしょうが、使用しなくても大して困らなかったという経験則に基づくものです
つまり必要無いと思う人は使わなければ良いし必要だと思う人は使えば良いだけじゃないでしょうか

112 :NAME IS NULL:2010/07/18(日) 14:00:29 ID:???
>>111
「必要なとき使う、不要なとき使わない、その基準は経験則」
そんな情報をネット上のフォーラムに残すことに何の意味がある?誰の参考になる?

どうせならその経験則を少しでも、ほんの一部でも噛み砕いて置いていってくれないか。

113 :NAME IS NULL:2010/07/18(日) 14:31:12 ID:???
>>111ではないが、RDB的なサロゲートキーってのはその名のとおり長大な
複合キーなど取り回しに難がある場合に代理として用いるものだろ。どのくらいで
「難がある」かはケースバイケース。
ただし、>>108の言うような「ユニークネスを保証する以外に意味のない」キー
というのは本来のサロゲートキーとは違って、OODBのIDのようなもの。
こいつらはデータモデルがそもそも違うんで、ごっちゃに議論すると発散する。

114 :NAME IS NULL:2010/07/18(日) 15:17:40 ID:???
顧客が決める気持ち悪いコードに対して
それと1対1になるように一見意味のなさそうなIDを振りなおすのがサロゲートキー。
(あとから仕様変更によって、1対1じゃなくなる可能性があるが)

単にテーブル設計の都合上の複合キーに対してIDを振りなおすのは
ちょっとわけが違うということか。

115 :NAME IS NULL:2010/07/18(日) 15:58:36 ID:???
いや、どっちかっつーとサロゲートキーというのは後者。
また、前者で1:1でなくなる仕様変更というのは、RDB的には「そんな仕様変更があったら
従属関係が変わってるからテーブル定義を変更せずに済むとは限らんだろ」となる。
これが有効なのは、OOあるいはER的に「オブジェクト/エンティティ境界はそれが持つ
属性やその関係よりも安定である」という前提でそのように設計した場合の話。

116 :NAME IS NULL:2010/07/18(日) 17:20:37 ID:???
サロゲートキーが必要/不必要で論じると、
複合キーを認めないという前提でないかぎり、すべて不必要だと思うが

ただ単に取り扱いが楽かどうかだけの問題以外に必要性があるなら教えてほしい

35 KB
■ このスレッドは過去ログ倉庫に格納されています

★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.02.02 2014/06/23 Mango Mangüé ★
FOX ★ DSO(Dynamic Shared Object)