- PR -

主キーの設定について

投稿者投稿内容
どんたくお
ベテラン
会議室デビュー日: 2005/08/29
投稿数: 88
投稿日時: 2005-11-08 17:25
vincentさん、ご返信いただきましてありがとうございます。


> 30回もデータベースアクセスするのは効率悪いんじゃないですか?
ごもっともでした。
vincentさんのご指摘のもと、30回のデータベースアクセスではなく、一度取得したものをプログラムで処理させると、すごい早くなりました。
// やっぱり、無謀でした・・・。


データベースの接続処理ってわりとコストがかかると再認識しました。
Java僧
ぬし
会議室デビュー日: 2003/11/06
投稿数: 261
投稿日時: 2005-11-08 17:57
引用:

SELECT day FROM holidays WHERE day like '200511%'
のようなSQLを使って1ヶ月分の休日を取得し、あとはプログラム側で
処理したほうが良いと思います。

パフォーマンス重視であれば年+月のフィールドを別に用意して
インデックスをつけておくのも良いでしょう。



うむむ・・・
別に用意したら「年+月のフィールド」(仮称 yearMonth)と day は
関数従属(day → yearMonth)という状態になりますよ?
二次正規化すらできていない表が出来上がります。

日付はRDBの日付型で保持するのがお勧めです。
postgresqlを含め多くのRDB実装で日付型は内部では数値として
扱われるので、上記のような範囲を指定するような場合も
インデックス(PK)がとても有効に作用します。

そして何より「2005-02-99」とかプログラムで異常値の
チェックをしなくてもよいことがメリットだと思います。
異常値は絶対無いことをRDBMSが保障してくれるのです。
だから、RDB"MS"なんですよ〜。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-09 01:38
日付加減算が楽にできるという理由で、がるがるさん同様、日付型を支持しますが・・・。

引用:
厳密には「年だけを条件にselectしたい」時などでDBへの処理コストが…とかって問題もなくはないのですが。



日付型の場合に 2005年だけ抽出
where ymd >= '2005/01/01 00:00:00' and ymd < '2006/01/01 00:00:00'

数値型の場合に 2005年だけ抽出
where ymd >= 20050101 and ymd < 20060101

処理コストに有意な差は見出せません。
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-11-09 10:57
どもです。がるです。
ちっと言葉足らずでした。
引用:

未記入さんの書き込み (2005-11-09 01:38) より:
引用:
厳密には「年だけを条件にselectしたい」時などでDBへの処理コストが…とかって問題もなくはないのですが。



日付型の場合に 2005年だけ抽出
where ymd >= '2005/01/01 00:00:00' and ymd < '2006/01/01 00:00:00'

数値型の場合に 2005年だけ抽出
where ymd >= 20050101 and ymd < 20060101

処理コストに有意な差は見出せません。


んっと。テーブルレイアウト年と月と日で別々に持つと
WHERE year=2005
で確認できるので、<>をもちいた、且つifが二つの演算よりは
多少違うだろう、という点で「処理コスト」って話をしたの
ですが。
もっとも「どの程度体感できるか」はかなり疑問です(苦笑
# というか、最適化されていることを少しは期待したい。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-09 12:06
引用:
テーブルレイアウト年と月と日で別々に持つと


timestamp と numeric( の処理コストの比較ではなく、numeric( と numeric(4), numeric(2), numeric(2) の処理コストの比較でしたか。それでも、フィールドを 年、月、日 に分けた場合でも複合主キーとして設定する場合には、時系列に物理データが格納されるのが一般的ですから、やはり処理コストは変わらないでしょうね。

引用:
WHERE year=2005 で確認できるので、<>をもちいた、且つifが二つの演算よりは
多少違うだろう、という点で「処理コスト」って話をしたのですが。


問い合わせクエリの記述量や複雑さは、直接、処理コストとは関係ないです。year=2005 であっても start < year and year < end であっても、テーブルが範囲スキャンされるのは一緒ですから。
どんたくお
ベテラン
会議室デビュー日: 2005/08/29
投稿数: 88
投稿日時: 2005-11-09 12:50
Java僧さんへ
未記入さんへ
がるがるさんへ

ご返信が遅くなってしまい、大変すみませんでした。
また、ご返信ありがとうございます。


皆様のご返答にGoogle先生にご協力いただきながら、ぎりぎりつい
ていってます。m(_|_)m
// 情けないです・・・。


> 日付加減算が楽にできるという理由で、がるがるさん同様、日付型を支持しますが・・・。
なるほど。
そうですね。

今回、皆様からご教授いただきまして、
year numeric(4), month numeric(2), day numeric(2)
char(8)
timestamp
明確にどれを主キー設定として用いるかについて、プログラム側や
データベース設計側などから様々な見解があり一概には判断できな
いと恥ずかしながら認識しました。

僕も皆様からのご意見を伺いしまして、今回は最終的に
year numeric(4), month numeric(2), day numeric(2)
primary key(year, month, day)
をしました。
// 日付というデータ型をRDBに持たすという意味で、timestamp
// と非常に迷いました。

皆様についていけるように、またがんばろうと思います。


皆様からは、多くのご意見、またわかりやすく説明していただけて、
本当に助かりました。
// 3ページへ突入するとは思っていませんでした。m(_|_)m
そして、データベース設計の難しさを改めて実感しました。


本当にありがとうございました。
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-11-09 12:58
がるです。
ちと興味があるので深めに。

引用:

未記入さんの書き込み (2005-11-09 12:06) より:
引用:
WHERE year=2005 で確認できるので、<>をもちいた、且つifが二つの演算よりは
多少違うだろう、という点で「処理コスト」って話をしたのですが。


問い合わせクエリの記述量や複雑さは、直接、処理コストとは関係ないです。year=2005 であっても start < year and year < end であっても、テーブルが範囲スキャンされるのは一緒ですから。


なるほど。
ちとDBMSのソース解析とかしたわけではないので想像の域を超えない
のですが。
なんとなく
コード:
while() {
  // 全テーブルのサーチループイメージ
  if (data->get_yy() == '2005') {
    return_data.push(data);
  }
}



コード:
while() {
  // 全テーブルのサーチループイメージ
  if ((data->get_ymd() >= '20050101') and (data->get_ymd() < '20060101')) {
    return_data.push(data);
  }
}


ということを最終的にやっているような気がしてまして。
この場合
if (data->get_yy() == '2005')
と比較して
if ((data->get_ymd() >= '20050101') and (data->get_ymd() < '20060101')) {
は「ifによる比較が常に2回行われる」事から、走っているCPU命令数が
増えるので処理コストもかさむのかなぁと思いまして。
# 正確には「左辺でfalseなら右辺の評価は行われない」事も多いので
# 単純に二倍ではないと思うのですが。

いやまぁ実際には色々最適化されてるんじゃないかと期待は
しているのですが & CPU命令で多少の増加があったとして
「体感できるか」ってのはまた別問題だと思うんですが。

もしかすると上述の前提が根本的に違うのかと思ったので、
もしなにかご存知ならとても興味がありまして。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-09 13:13
引用:
ちとDBMSのソース解析とかしたわけではないので想像の域を超えないのですが。


範囲スキャンの場合は、そもそも各レコードに対して該当するかどうかというチェックが行なわれません。レコードごとの合致検査に使われる if 文の複雑さという発想が、まずズレています。

もちろん、すべてのデータベースの実装がそうだとは言い切れませんし、あなたのいうようなシンプルな構造のデータベースも存在するかもしれませんが、パフォーマンスを考えると一般的ではないと思います。

スキルアップ/キャリアアップ(JOB@IT)