- PR -

ユニークキー生成

投稿者投稿内容
ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-05-13 13:43
なかなか白熱してますね。

みなさん、それぞれの経験があると思いますが、私はどれも正解だと思います。
一つの仕様を実現する方式はたくさんあって、制約条件(ユーザ要求や環境、開発効率など)を加味した結果、メリット・デメリットを認識したうえで最適な方式で実現するのが開発者の役目(頭の使いどころ)なわけで、一概にどうとは言えないですよね。

私の場合は「とりあえずDB側での実現可能性から検討する」ポリシーです。
アプリケーションで実現しようとした場合、少なからず重複する危険性があるわけで、みなさんおっしゃるように、安全性を保証するための検証処理がどうしても必要です(真にユニークの必要があるならば)。
#私の場合、やらなくて済むことをやるとバグが増えちゃうもんで、どこかでやってくれることは、そこにお願いすることにしてます。そして、なるべく奥のほうで解決してもらって、こっちは楽をしたいと考えます(ま、どっちも私が作るんですが・・・)

ただ、DBに機能があるからと自動採番させるのは、必ずしもメリットばかりではないと思います。
例えば、オフラインでも実行できるように、オンラインになるまでローカルに保存しておいて、オンライン時に同期するという方式を考えたとします。
ユニークキーが必要なところで仮の値を入れておいて、同期時に確定値で更新するという手もありますが、ローカルの時点で値が確定していれば、双方向同期じゃなくて更新処理だけで済みます。つまり、そのアプリケーションが本当にオンラインにならなくても、ExcelやらCSVやらXMLなんかのローカルファイルを吐き出してメールで「更新しといてぇ」と依頼する運用ができるわけです。他ユーザは、そのデータを閲覧する必要はあるが、更新はしないというケースでは、こういうやりかたもアリです。

アプリケーション側でユニークキーを作る場合、再現性を求める場合は乱数、そうじゃない場合はGUIDを使うことが多いのですが、ほかに何か面白い方法はないでしょうか?
七味唐辛子
ぬし
会議室デビュー日: 2001/12/25
投稿数: 660
投稿日時: 2005-05-13 14:12
自分の場合はこのやり方が多いです。

select max(ほげほげ) + 1
where テーブル名
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-05-13 18:45
どもです。がるです。
ちょいと順番が前後します。
あと、結構長くなりました。すみません ^^;

引用:

ほげたさんの書き込み (2005-05-13 13:43) より:
みなさん、それぞれの経験があると思いますが、私はどれも正解だと思います。
一つの仕様を実現する方式はたくさんあって、制約条件(ユーザ要求や環境、開発効率など)を加味した結果、メリット・デメリットを認識したうえで最適な方式で実現するのが開発者の役目(頭の使いどころ)なわけで、一概にどうとは言えないですよね。


ですねぇ。そんなもんだと思います。
個人的には
・手持ちのカードを多く
・各カードの長所と欠点を把握
ってのを心がけたいなぁ、と。

個人的には
時間キーの長所
・SQLとの通信がないのでトラフィック的にお手軽
・DBMSが変更になっても問題がない
・DBサーバがものすごくタイトに動いている場合、処理をクライアント側に分散できる

DBキーの長所
・(DBを移動しない限りにおいて)楽に実装できる
・一意性などの問題がきちんと処理されている
・クライアントの資源をあまり食わずに実行できる

こんな感じですかね?
ほかにも色々ありそうなのですが。

引用:

未記入さんの書き込み (2005-05-13 12:29) より:
データベースを単なるストレージとしてしか使用しない・できないプログラマが増えていますね。一意制約も外部参照制約も全部プログラムでチェックしているからいいんだっ!っていう人がたまにいるけど、私はそういった意見には賛成できない。


まぁ、この辺は賛否両論かと。
ただ、DBMS自体が変更になる際のSQLの互換性、DBMSが食う資源の多さ、などから考えると、「できる」と「やってよい」にはまた少し隔たりがあるように思われるのですが如何でしょうか?
ロジックが分散するのも個人的にはあまり好まないところですね(特にストアドプロシージャ周り)。

引用:

なるべくデータベースの機能を使用して安全性を高めるべきです。


この辺の理由は…

引用:

該当テーブルを操作するすべてのクライアントプログラムがルールに従わなくてはならないという厳しい縛りがつきます。そのプログラムを使ってるだけなら問題は起きないかもしれませんが、通常運用外の保守作業で SQL*PLUS や クエリアナライザで直接データを流し込む要件が発生したときに困りませんか?


この辺からきてるのでしょうか?
確かに「該当テーブルを操作するすべてのクライアントプログラムがルールに従わなくてはならないという厳しい縛りが」つきますが、それは「DBMS側の機能を使うプログラム」にしても同様だと思います(すべてのプログラム中のSQLが必ずシーケンスのルールに従わなくてはいけないので)。
といいますか。「該当テーブルを操作するすべてのクライアントプログラムが」とありますが、これは「1テーブルを操作するプログラムがあちこちに散らかってる」んでしょうか?
それは、その設計のほうに問題がないですか?

引用:

(私の今までの経験から) 作りこまれた専用プログラム(入力画面?)だけで、すべてのデータを登録できることは非常に稀だと思っています。初期データのインポートだけでなく、運用開始後でも 専用プログラムを用いない様々なデータの流し込みが発生することは多々あります。そういったときに特定のプログラムに実装されたチェック機能が必要になっていると手作業ができなくて非常に困るものです。


んっと…「特定のプログラムに実装されたチェック機能」とは何を指しているんでしょうか?
今回のお話はキーの作成のお話で。
で、「データを用意して一気にインポート」であれば、いくらでも色々な手段が取りうるかと思うのですが。
# いやまぁ。個人的には、インポートも実際の業務も、同じクラスを作って作業するので何の問題もなく「同一に」出来ますが。
# というか、1テーブルのINSERTをする部分が「複数箇所」あるのだと仮定すれば、それ自体に設計のミスとかありませんか? 先ほども記述しましたが。
# あと、テストデータ程度ならともかくとして、「SQLを直接叩いて本番DBにINSERT」って状況も私的にはあまり好ましいようには思われないのですが。そういった点では「手作業ができなくて非常に困る」については「むしろ困っててほしい」部分でもあります。

引用:

それに、SQL Server にも Oracle にも 連番を採番する機構が備わっているのに、それを使わず、独自のユーザーコードで一意性を確保するロジックを実装する積極的な理由が私には思いつきません。


備わっています。それについては、きっちりと。それを否定するつもりもないですし、してもいないと思います。
それを言ってしまえば、それがOracleであれDB2、Sysbaseであれ、MySQLやPostgreSQLであれ、そういった機能はあります(通常、DBMSとしてまともなら大抵ついてるんじゃないでしょうか?)。
私が気にしている第一のポイントは
・互換性がない
事です。
例えば。SQL serverにそぐう書式でSQLを書いた状態で「DBをMySQLに変更」するときに、それが容易に出来ますでしょうか?
# まぁ「その辺をクラス作ってラッピング」ってのは実際1手段として存在しうるのですが :-P
ただ、そういった「DB間での互換性」の問題は、特に私の場合は周囲の環境柄、非常に気にかかります(そうは言っても納品直前にDBチェンジしたいって言われるのはそろそろ避けたいお年頃なのですが :-P )。
もう一つ。これはあえて書かなかったのですが。「DBサーバの資源問題」も、正直にいうと少々気になります(特にOracle)。
まぁ、この辺は「気にしなくても」という部分でもあるのですが、古い人間なので、つい…ってところでしょうか?
ただ、正直言ってDBMSってどの製品をとっても「重い」です。高機能である分止むを得ないのはわかっているのですが。その辺の重さが問題になるレベルにシビアなコードを要求されるときは、やっぱりボトルネックのDBMSには「データストレージとしてシンプルな動作」以上のことは、可能な限りさせたくないってのも本音の一つです。

私は、別に「DBサイドで一意にする」機能を否定しているわけではないです。
ただ、そこにはそれなりの問題点もあり、懸念点もあり、その代替案としての1提案をしたい、という程度のスタンスなのですが。

で。最後にちょっと厳しい一言を。
引用:

# 自分で何でも組もうとするのは、バカなプログラマ。
# 他(ミドルウェア)でできることは端折って楽するのが、ふつーのプログラマ。


ということはqmailの作者はバカなのですな?
とかいう突っ込みはおいといて。
未記入さんに一つだけ質問をしておきましょう。
「その人は"なぜ"わざわざ自分で実装をしようと思い立ったのか?」

この問いに「バカだから」「無知だから」と答えるのは簡単。
でも、果たしてその回答は真実なのでしょうか?
「自分の知らない」「より深い」なんらかの理由を秘めている可能性は本当にないのでしょうか?
他人を否定するまえに、その根底にあるものを理解しようとする姿勢があってもいいように思うのですが如何なものでしょうか?

私は、Perlでいう「車輪の再開発」も、場合によっては有益だと考えてます。


[ メッセージ編集済み 編集者: がるがる 編集日時 2005-05-13 18:48 ]
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2005-05-13 22:17
がるがるさん、こんばんは。

ここ↓だけ反応。
引用:

私が気にしている第一のポイントは
・互換性がない
事です。
例えば。SQL serverにそぐう書式でSQLを書いた状態で「DBをMySQLに変更」するときに、それが容易に出来ますでしょうか?


うーん、ある程度開発が進んだ時点で、そうそう容易にDBを変更出来たりするもんなんでしょうか…。
例えば SQL 一つにしても、演算子や関数、外部結合の構文だって違いますから、完全に互換性を持たせる事って不可能に近いのではないかと。
ロックだとかの挙動の違いも結構、ダメージ大きかったり。

互換性のために性能を犠牲にするよりは、ストアドでもヒントでも駆使すべきだと、個人的には思います。

という事で、異なるDBに対応しようと思ったら、結局こういうような手段↓が現実的なんじゃないでしょうか。

引用:

# まぁ「その辺をクラス作ってラッピング」ってのは実際1手段として存在しうるのですが



【追記】

引用:

やっぱりボトルネックのDBMSには「データストレージとしてシンプルな動作」以上のことは、可能な限りさせたくないってのも本音の一つです。


って、あれ? 目的は一緒なのに考え方が違いますね。
ボトルネックになりがちだからこそ、DBMSに固有な、互換性のないSQLでも積極的に採用すべきだと思うんですが…。
想定している用途とかが違うのかな?


[ メッセージ編集済み 編集者: きくちゃん 編集日時 2005-05-13 22:38 ]
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2005-05-13 23:07
unibon です。こんにちわ。

引用:

ほげたさんの書き込み (2005-05-11 13:11) より:
自前でユニークなキーを、ということであれば、整数型にしておいて MAX(カラム)+1 とする手もありますし、GUIDを使う手もあります。どちらにしろ、トランザクションやユニーク性のチェックが必要となりそうですが・・・


引用:

ほげたさんの書き込み (2005-05-13 13:43) より:
アプリケーション側でユニークキーを作る場合、再現性を求める場合は乱数、そうじゃない場合はGUIDを使うことが多いのですが、ほかに何か面白い方法はないでしょうか?


ちなみに、Access なら主キーに GUID を使うこともできたと思います(Access の機能なのか Jet の機能なのかは分かりませんが)。
GUID を使えば原理的に重複は気にしなくて良いのでしょうけど、コストが高そうで私は今だかつて使ったことがありません。でも興味はそそられます。本当に本当に重複しないのかが気になるところですが。
もっとも、人為キー(人工キー)を使わないですめば、このようなキーの生成に気を使う必要もなくなりますが。
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-05-14 00:01
どもです。がるです。

引用:

きくちゃんさんの書き込み (2005-05-13 22:17) より:
ここ↓だけ反応。
引用:

私が気にしている第一のポイントは
・互換性がない
事です。
例えば。SQL serverにそぐう書式でSQLを書いた状態で「DBをMySQLに変更」するときに、それが容易に出来ますでしょうか?


うーん、ある程度開発が進んだ時点で、そうそう容易にDBを変更出来たりするもんなんでしょうか…。
例えば SQL 一つにしても、演算子や関数、外部結合の構文だって違いますから、完全に互換性を持たせる事って不可能に近いのではないかと。
ロックだとかの挙動の違いも結構、ダメージ大きかったり。


んっと。ダメージは、それはでっかいです。なんていうか、クライアントに
ストレートに殺意を抱けるくらい :-P
ただ、現実問題として、お客様は場合によっては「あっさりと」そういう
発言をなさいます。
つまり。
「そんなのは技術的におかしいし不可能だし変だ」と騒ぐのは容易なのですが、
現実問題として、対応をせざるを得ない状況が目の前に転がっておりまして。
したがって(無論クライアントを見ての判断にもなるのですが)、ある程度、
そういったことへのリスクヘッジとしての手段が必須となるわけです、ハイ。
# おかげで、そーいった手段には現在事欠いておりません。…不幸なことに。

引用:

互換性のために性能を犠牲にするよりは、ストアドでもヒントでも駆使すべきだと、個人的には思います。


ここについては微妙ですね。
つまり、
・互換性重視
・性能重視
がすでに現場で違いますし。
で、さらに性能重視であるがゆえに「ストアドを使わない」設計をしたこともありますし。
端的には「HTTPサーバ(SQL的にはクライアントマシン)がクラスタリングで
いっぱい(たしか10台ちょいでした)、DBは1台」というケース。
DBのマシンにもそれほどコストがかけられるわけではなく(ある程度は
よいものでしたが、劇的に、というほどでは無かった記憶があります)。
こういったケースの場合、DBマシンがボトルネックになりやすいため、
「処理は可能な限りクライアントでこなす」必要がありました。

この辺はやっぱり「現場次第」なので、正解はないですね(苦笑

引用:

という事で、異なるDBに対応しようと思ったら、結局こういうような手段↓が現実的なんじゃないでしょうか。
引用:

# まぁ「その辺をクラス作ってラッピング」ってのは実際1手段として存在しうるのですが :P




はい。結構使えます。っていうか、このパターンで
・異なるDBで通用するようにSQLを生成する
クラス群とか持ってます。
# 便利なんですけどねぇ。歴史的経緯を考えると…ちょっとストレスが(笑

引用:

【追記】
引用:

やっぱりボトルネックのDBMSには「データストレージとしてシンプルな動作」以上のことは、可能な限りさせたくないってのも本音の一つです。


って、あれ? 目的は一緒なのに考え方が違いますね。
ボトルネックになりがちだからこそ、DBMSに固有な、互換性のないSQLでも積極的に採用すべきだと思うんですが…。
想定している用途とかが違うのかな?


上記に書いたとおりなのですが。端的には
・クライアントマシンには負荷をかけてもよいがDBマシンには負荷をかけたくない
用途、というケースですね。

以上…ちゃんとしたコメントになりましたでしょうか?
質問疑問ご意見などあったらまたよろしくお願いします ^^
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-05-14 02:00
引用:
DBMS自体が変更になる際のSQLの互換性(中略)互換性がない(中略)SQL serverにそぐう書式でSQLを書いた状態で「DBをMySQLに変更」するときに(中略)「DB間での互換性」の問題


データベースが差し替え可能と考えている時点で、私とはシステム設計ポリシーが異なると思いますので、もうこれ以上は何も言いますまい。お好きなようにどうぞ。

引用:
引用:
# 自分で何でも組もうとするのは、バカなプログラマ。


で。最後にちょっと厳しい一言を。(中略)「その人は"なぜ"わざわざ自分で実装をしようと思い立ったのか?」(中略)なんらかの理由を秘めている可能性は本当にないのでしょうか?


何が言いたいのか良く分からないんですがね。理由があって再実装を行うというのは、(理由もなくすべてのコードを)何でも自分で組もうする行為にはあたらないんじゃないですか。良く知りませんが。あるものはすべて使え、車輪の再発明をひとつでもする奴はバカだ、と言った覚えはありませんよ。良く知りませんが。

まあ、未記入に噛み付きたいだけの人みたいなんで、もう相手はしません。あとはお好きなようにどぞー。
がるがる
ぬし
会議室デビュー日: 2002/04/12
投稿数: 873
投稿日時: 2005-05-14 13:39
どもです。がるです。

ちょいと脱線の質問で恐縮なのですが。
引用:

未記入さんの書き込み (2005-05-14 02:00) より:
引用:
DBMS自体が変更になる際のSQLの互換性(中略)互換性がない(中略)SQL serverにそぐう書式でSQLを書いた状態で「DBをMySQLに変更」するときに(中略)「DB間での互換性」の問題


データベースが差し替え可能と考えている時点で、私とはシステム設計ポリシーが異なると思いますので、もうこれ以上は何も言いますまい。お好きなようにどうぞ。


なるほど。設計というか、状況環境が違うことはよく理解しました。
で、ちょいと質問なのですが。

私の場合、もっぱら専門がUNXI(特にLinux)で、CGIの言語はおおむね「一通り」
という受け方です(正確にはC、C++、Perl、PHP、Javaあたり)。
サイズ的には、大手さんもあるのですが、やはり中小さんが多いです。
で、私の受けている限りですと、DB差し替えは比較的よく発生し、また
クライアントからの要求も多いのが実情です。
# システムのサイズUp/Downから、単純に環境上の問題とか上のほうの人のご意向とか

未記入さんのお話の限りですとあまりDBMSの変更要求のない環境である
ようなのですが、よかったらOSとか規模とかを伺ってみたいです。

…いや。単純にうらやましいだけって話もありますし。逆を返すと
「私のクライアント教育にミスがある」だけのような気もするのですが :-P

あと。
引用:

何が言いたいのか良く分からないんですがね。理由があって再実装を行うというのは、(理由もなくすべてのコードを)何でも自分で組もうする行為にはあたらないんじゃないですか。良く知りませんが。あるものはすべて使え、車輪の再発明をひとつでもする奴はバカだ、と言った覚えはありませんよ。良く知りませんが。


なるほど。前述の書き込みには「理由」という単語が無かったのでちょっと気になりまして、その程度の話でした。

引用:

まあ、未記入に噛み付きたいだけの人みたいなんで、もう相手はしません。あとはお好きなようにどぞー。


んっと…噛み付きたいわけではなくて。私とは異なる考えを持っているように思われたので、お互いの意見をぶつけて議論を展開して、話を膨らせて見たかったのですが…。
もしなにかお気に触るようなことがありましたらお詫びいたします。

ただ、恐らくは多くの人が「異なる背景」「異なる環境」「異なる世界観」でお仕事をされている人たちだと思うので。
できれば感情論は抜きで、お互いの世界観に立脚した話を展開しつつ、相手の世界観への「否定」ではなく「疑問」と「意見」をぶつけ合えるような会話が出来たらよいなぁ、と思っております。

そういう意味で、恐らくは結構違う背景を持つであろう未記入さんにも、色々とお話を伺えるといいなぁ、と思ってます。

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