- - PR -
最終行にinsertされない?
投稿者 | 投稿内容 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2005-11-14 23:47
こんばんは。
RDB素人がこんなところで発言するのは恐縮なのですが…
そもそもORDER BYも使わずに、 レコードが何らかの順で並ぶことを期待すること自体間違っていないでしょうか。 DB内部のデータの物理的な格納順序なんて、通常どうでもよいことでしょうし。 複数のクライアントから同時にレコードがINSERTされた場合 Dukeさんのおっしゃるように同じ登録日時となってしまうことがあるでしょうね。 そして登録日時でORDER BYしても、いつも同じ順序で取得できる保証もないでしょう。 そういう場合は、MDBなんかのオートナンバーがあればいいのでしょうけれども SQL Serverにはなかったように思うのですが… どうしても、ちゃんと登録順序で並べたいなら… 私が業務系システムに携わった(数少ない)経験から、 「伝票番号の採番」方法なんかが参考になると思いますが… 具体的には、 「番号マスタ」みたいなのを用意しておき、IDとして使う番号を入れておきます。 レコードをINSERTする直前に、「番号マスタ」を排他ロックして番号を取得し(SELECT FOR UPDATEでしたっけ?) 同時にインクリメントします。 次にレコードにID(主キー)かなにかとして、その番号を設定するという方法です。 この方法だと、ちゃんと登録順に一意にソートできると思うのですが。 #…なんて私なんかがこんなところで、釈迦に説法してしまいました。スイマセン(~_~;) | ||||||||||||||||
|
投稿日時: 2005-11-15 00:17
IDENTITY が ありますよ。 | ||||||||||||||||
|
投稿日時: 2005-11-15 00:20
... from 番号マスタ with (UPDLOCK) ですね。(排他ロックではなく更新ロックで十分だと思いますので UPDLOCK と書いています。読み取りも禁止したいなら排他ロック XLOCK になります。) | ||||||||||||||||
|
投稿日時: 2005-11-15 00:33
こんばんは。
あ、やっぱりデタラメだらけなことばっかり、書いてましたか(~_~;) つっこみどころ満載でしたね。スイマセンでした。 | ||||||||||||||||
|
投稿日時: 2005-11-15 08:30
正直、私も関係ない気が……
物事には「決まっている」ことと「たまたまそう見える」ことがあります。 これは、「たまたまそう見える」だけに過ぎません。 私はSQL Serverのマニュアルは見たことはありませんが、SQLの解説部分のORDER BYのあたりに「順序は保証されない」と書いてあるのではないでしょうか?それが「決まっている」ことです。 保守やっていると、結構ORDER BYつけてないことが原因のバグがあることに驚かされます。 参考までに、ググったら、こんなの出てきました。 | ||||||||||||||||
|
投稿日時: 2005-11-15 11:14
ジョウジさんこんにちは。
> 最終行にinsertされないということに関連するようには見えない どこにinsertされるかわかりませんし、どこからとってくるかもわかりません。 その時々によって一番落ち着きやすいところにデータが入るのだと思います。 また、表示も、一番速く表示できるように表示しているだけでしょう。 SQLサーバーの実装がどのようになっているのかは(私は)わかりませんが、 常に同じ順序ででてこないところを見ると、最後に追加されたものは 最後に表示されるというわけではなく、途中に空きがあれば、 そこにインサートされる(ように見える)こともあるようですね。 (もっとも表で見るのでなければ順序という概念が元々ないのですが...) > 通常ですと最終行にinsertされてますよね? ほとんどの場合はそう見えますが、データの格納効率の関係などで 時々期待とは違って見えることもある。ということです。 SQLサーバーでどのような場合にそうなるのかは(私は)わかりません。 (技術情報で公開されているのかな?) 使う人は、表示・格納の順序は常に一定であるとは期待できない ということだけわかっていればいいのだと思います。 | ||||||||||||||||
|
投稿日時: 2005-11-15 23:52
insertする位置は実はわりと決まっていたはずでは。
clusterdで作成されたindexの順で物理的に格納されるのが原則だけど 例外があります。 注)ここで物理的といったのはleaf(後述)の中でのみのこと 各leafは物理的に順番には並んでいません dbccかsp_○○で並べる方法はあったかも知れませんが! で、例外は。。 fill factor(leafの確保する空き領域の比率)が0や小さい場合、 また大量の新規レコードが追加された場合に leaf(テーブルの実際のデータの集まりとあらかじめ確保している空き領域)に 新しい行が格納できない事があり、その時leafを二分する作業が発生するため その作業中は一時的にorder byの無いselectでは取得順が一定しない現象が出る。 たしかleafは物理上では8000バイトの記憶領域ぐらいしか無かったような、 それがそのまま一レコードに格納できる上限になったはず(これは自信無し) SQL ServerがCPUの空き時間にleafでの取得順にclusterd indexを並び替えるので 特に更新が頻繁でならば取得順はclusterdで作成されたindexの順で落ち着くはず ただしこの時の取得順はTableScanかclusterd indexを使用した場合に限ります。 whereを指定したりjoinをした瞬間に何かしらの使用したindexの順番に 取得してくるはずです。 ただ4年前に受けた講習の記憶なので自信はそれほどありませんが こんな感じだったと。Versionは2000の話です 結論としては「order byを使用しなさい」って事だと思います 結局それかよって感じですね [ メッセージ編集済み 編集者: marine7 編集日時 2005-11-16 00:40 ] | ||||||||||||||||
|
投稿日時: 2006-03-28 19:51
こんばんは。
今更ですが、この件に関して質問があります。 ソートに関してはこのスレッドの通りの理解をしていました。 が、本日同僚の方から 「プライマリーキーはデフォルトでソートキーとなる」といわれました。 具体的には コード1 コード2 コメント 000001 01 Comment01 000001 02 Comment02 000001 05 Comment05 000001 11 Comment11 000001 96 Comment96 000001 99 Comment99 というデータがあります。 ( コード 1 とコード 2 がプライマリーキー ) で、普通に select * from テーブル; とすると上記の順番で取得出来ます。 その後、 000001,03,Comment03 のデータを登録して再度 Select をすると新規登録したデータは 02 と 05 の間で出力されます。 「たまたまソートされたような結果が表示されただけ」といわれればそうなのですが、 同僚が「デフォルトソートという機能があるはずです」と言うのです。 そっちのソースが出てくれば、それはそれで良いのですがそんな物を聞いたことが無いので どうしたもんかな、と思っています。 どなたか「デフォルトソート」のような機能を聞いたことがありますでしょうか? ちなみに、環境は「Oracle 9i」です。 宜しくお願いいたします。 |