- PR -

最終行にinsertされない?

投稿者投稿内容
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-11-14 23:47
こんばんは。
RDB素人がこんなところで発言するのは恐縮なのですが…

引用:

Dukeさんの書き込み (2005-11-07 19:33) より:

例えばテーブルが以下のようになっていた場合

名称 登録日時
・  ・
・  ・
Z 200511070000
A 200511071834
B 200511071834

登録日時でorder byした結果が上記の場合、
次にinsertするデータが名称:C、登録日時2005年11月7日18時34分となっていた場合に
Bの下にこのデータはinsertされるのでしょうか?

最終行に追加されるということとorder byの関連性が見えてきませんで・・・。
申し訳ございません。



そもそもORDER BYも使わずに、
レコードが何らかの順で並ぶことを期待すること自体間違っていないでしょうか。
DB内部のデータの物理的な格納順序なんて、通常どうでもよいことでしょうし。


複数のクライアントから同時にレコードがINSERTされた場合
Dukeさんのおっしゃるように同じ登録日時となってしまうことがあるでしょうね。
そして登録日時でORDER BYしても、いつも同じ順序で取得できる保証もないでしょう。

そういう場合は、MDBなんかのオートナンバーがあればいいのでしょうけれども
SQL Serverにはなかったように思うのですが…


どうしても、ちゃんと登録順序で並べたいなら…
私が業務系システムに携わった(数少ない)経験から、
「伝票番号の採番」方法なんかが参考になると思いますが…

具体的には、
「番号マスタ」みたいなのを用意しておき、IDとして使う番号を入れておきます。
レコードをINSERTする直前に、「番号マスタ」を排他ロックして番号を取得し(SELECT FOR UPDATEでしたっけ?)
同時にインクリメントします。
次にレコードにID(主キー)かなにかとして、その番号を設定するという方法です。

この方法だと、ちゃんと登録順に一意にソートできると思うのですが。

#…なんて私なんかがこんなところで、釈迦に説法してしまいました。スイマセン(~_~;)
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-15 00:17
引用:

そういう場合は、MDBなんかのオートナンバーがあればいいのでしょうけれども
SQL Serverにはなかったように思うのですが…


IDENTITY が ありますよ。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2005-11-15 00:20
引用:

「番号マスタ」を排他ロックして番号を取得し(SELECT FOR UPDATEでしたっけ?)


... from 番号マスタ with (UPDLOCK) ですね。(排他ロックではなく更新ロックで十分だと思いますので UPDLOCK と書いています。読み取りも禁止したいなら排他ロック XLOCK になります。)
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-11-15 00:33
こんばんは。

引用:

未記入さんの書き込み (2005-11-15 00:17) より:
引用:

そういう場合は、MDBなんかのオートナンバーがあればいいのでしょうけれども
SQL Serverにはなかったように思うのですが…


IDENTITY が ありますよ。



引用:

未記入さんの書き込み (2005-11-15 00:20) より:
引用:

「番号マスタ」を排他ロックして番号を取得し(SELECT FOR UPDATEでしたっけ?)


... from 番号マスタ with (UPDLOCK) ですね。(排他ロックではなく更新ロックで十分だと思いますので UPDLOCK と書いています。読み取りも禁止したいなら排他ロック XLOCK になります。)



あ、やっぱりデタラメだらけなことばっかり、書いてましたか(~_~;)
つっこみどころ満載でしたね。スイマセンでした。
まいるどきゃっと
大ベテラン
会議室デビュー日: 2004/08/12
投稿数: 135
お住まい・勤務地: 群馬
投稿日時: 2005-11-15 08:30
引用:

ジョウジさんの書き込み (2005-11-14 22:19) より:
引用:

なか-chanさんの書き込み (2005-11-14 09:54) より:
http://www.geocities.jp/mickindex/database/db_whyname.html



SQL Server 2000が関係モデルの関係で
最終行にinsertされないということに関連するようには見えないのは
私だけでしょうか?



正直、私も関係ない気が……

引用:

通常ですと最終行にinsertされてますよね?
で、selectすると普通に最終行に表示されている。
これってどう解釈するんだろって。



物事には「決まっている」ことと「たまたまそう見える」ことがあります。
これは、「たまたまそう見える」だけに過ぎません。
私はSQL Serverのマニュアルは見たことはありませんが、SQLの解説部分のORDER BYのあたりに「順序は保証されない」と書いてあるのではないでしょうか?それが「決まっている」ことです。
保守やっていると、結構ORDER BYつけてないことが原因のバグがあることに驚かされます。

参考までに、ググったら、こんなの出てきました。
なか-chan@最愛のiMac
ぬし
会議室デビュー日: 2002/07/17
投稿数: 385
お住まい・勤務地: 和光市・世田谷区
投稿日時: 2005-11-15 11:14
ジョウジさんこんにちは。

> 最終行にinsertされないということに関連するようには見えない

どこにinsertされるかわかりませんし、どこからとってくるかもわかりません。
その時々によって一番落ち着きやすいところにデータが入るのだと思います。
また、表示も、一番速く表示できるように表示しているだけでしょう。
SQLサーバーの実装がどのようになっているのかは(私は)わかりませんが、
常に同じ順序ででてこないところを見ると、最後に追加されたものは
最後に表示されるというわけではなく、途中に空きがあれば、
そこにインサートされる(ように見える)こともあるようですね。
(もっとも表で見るのでなければ順序という概念が元々ないのですが...)

> 通常ですと最終行にinsertされてますよね?

ほとんどの場合はそう見えますが、データの格納効率の関係などで
時々期待とは違って見えることもある。ということです。
SQLサーバーでどのような場合にそうなるのかは(私は)わかりません。
(技術情報で公開されているのかな?)

使う人は、表示・格納の順序は常に一定であるとは期待できない
ということだけわかっていればいいのだと思います。
marine7
会議室デビュー日: 2005/11/15
投稿数: 1
投稿日時: 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 ]
小僧
大ベテラン
会議室デビュー日: 2005/06/24
投稿数: 122
投稿日時: 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」です。
宜しくお願いいたします。

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