ストアドよりインデックスのほうが速いよ
なんかね、データベースからデータを取得して VB で簡単な加工して、
書き戻すっていう更新処理があったのよ。当然、C/S 間のピンポン多発で
非常に遅いでやんす。で、「バッチ更新はストアドで書き直したらどうですか?」って
上司に言ったわけです。勇気をふりしぼって。
そしたら「ストアドよりインデックスのほうが速いよ」って。(゚Д゚)ハァ?
「クエリ単体の実行時間は 50ms 以下なので遅いのは呼び出しのオーバーヘッドが…」
「データベースが遅いのはね。インデックスなんだよ。たとえば、君の言う
50ms がインデックスを工夫することで 20ms になったら倍以上に速くなるんだよ。」
「いや、50ms が 20ms になっても体感できないと思うんですが…」
「そんなことやってみなくちゃ分からないだろ!!! やりもしないで何を
言ってるんだよ。インデックスは奥が深いんだよ」
「いまでも主キー指定での取得になっていて…」
「もういいよ。オレがインデックス張ってやるから、まあ見てから言えよ。な?」 また、VB も使えない厨が来たのか ?
まず、「(DB使うのにVB使うのやめれ) 」の具体的理由を書いてみそ。 ストアドよりインデックスのほうがてっとり早いのは常識。
議論の余地なし。 VBアプリでメモリ多く使うと落ちる。
画面のコンポーネントべたべた貼る程度でキョドる。 まとめて大量のレコードを更新するような処理はテーブルロックがかけられるなら
いいのですが、通常運用中に実行しなければいけないときはどうしてますか?
where無しなどの大域処理をしてしまうと1命令を1トランザクションで実行しよう
とするから、ロックは広い範囲にかかりまくるし、オラクルだとロールバックセ
グメントに書き出しまくる。そのせいか処理が妙に重たい。
ストアドでカーソル使ってwhere current ofで処理しても、ループで内でupdateや
insert命令を実行してもロックやRBSがらみのリソースを消費してる感じです。
仕方がないのでクライアント側に一旦対象のレコードのキーをすべて書き出して、
それをキーにして数十件ずつコミットしながら更新かけてゆく方法をとったら
俄然処理が速くなりました。
こういうケースでは一般的にはどうするのがいいのでしょうか? >仕方がないのでクライアント側に一旦対象のレコードのキーをすべて書き出して、
これをDB内で済ませろ >29
プリコンパイル(静的SQL)とストアドプロシジャは全く別のものだよ。 >>38
tempテーブルが使えるならそうするんだけど残念ながらOracle8なので使えません。
ログ運用してるんで通常テーブルをワークには使いたくないのです。
>>39
別の概念ではあるがプリコンパイルされないストアドって見たことはないですね。 コンパイルといっても構文解析フェーズを済ましておく程度だけどね。
最初の実行時にコンパイルするタイプのを見かけますな。
>>37 はストアドが必ずしも役に立つわけでない例を挙げてみてるんだろうな。
OracleのPL/SQLだと普通の手続き型言語に似てるからとっつきは良いけど
使い方は要注意だ。非効率な変な書き方もできてしまうからな。 >>36
OS かお前のマシンがしょぼいんじゃねーか ?
あるいは、バグバグしてるコンポーネント使いまくりとかな。 そもそもバッチ更新なのにコンポーネントは全く関係なし。
アプリに負担をかけることすら間違い。
それとクライアントに一端処理を移すとのことだけれども
ストアドやインデックス云々より、DBの構造を見直した
方が早いよ。 ストアドよりインデックスのほうがてっとり早いのは常識。
議論の余地なし。
ボトルネックを調べてみるのにまず手っ取り早い索引から調べるというのは
同意だが、実際の対策としてストアドとインデックスを比べるのは意味はない。
まったく別物だからなぁ。
要領を得ないことをいう部下を信用しないのは上司の基本だと思うな(笑) >>1を叩くのは2チャンネラの基本だと思うな(笑) ←笑って付けるだけでキモヲタ風味になる。 >>46-47
オマイラ、論点がずれてる。
>>48
正解
>>1の場合であればストアドのようなサーバサイドの処理にした方がパフォーマンスが上がると思う。
さらに、可能であれば、『UPDATE ・・・ SELECT』 文にした方がベターだな
>>51
論点がずれてる。
上司が言ったのは、すばやく目標を達成するにはって話だ。
よって、インデックスで良いんだよ。
それを>>1が高速化技法の話に摩り替えた。
よく読め。 >>52
>よく読め。
>>1
>「いまでも主キー指定での取得になっていて…」
莫迦麦価 >>53
お前こそよく読め。
>「いまでも主キー指定での取得になっていて…」
何で主キー指定して取得してるのにストアドなんだよ?
意味無いだろ。
その点を上司がたしなめたんだろ。
きちんとインデックス張ってまともなクエリ書けと言う意味だろ。
お前はストアドなどとの給う前にやることがあるだろ?と言われたわけだ。 なんつーか、やれやれですな。
>>54
>何で主キー指定して取得してるのにストアドなんだよ?
>意味無いだろ。
ストアドプロシジャの利点は、RDB サーバの _プロセス内で
処理が閉じている_ 点にある。その為、>>1 の指摘する
>C/S 間のピンポン多発で非常に遅いでやんす。
が解消される事が期待できる。
一方、主キーには _既にインデックスは作成されている為_、
二重にインデックスを張る行為には _全く意味がない_。 >>55
同意。やれやれだよ。
>>54あたり本気なのかネタなのかすら判別がつかん。
何でこんな基礎的な話で議論になるのか…。
主キー指定して取得するからピンポンが発生するんだろ。
なぜ、主キー指定して取得してるのに、ピンポンを発生させているのか考えれば、
わかる話だろう。
まともなSQL書けばすむ話だ。
ストアド以前の話だな。
よってインデックスが正しい。 >>57
( ゚Д゚)ポカーン
考えれば分かる話だろう。
じゃなくて、そこんとこ詳細に説明してみ。
どんな珍説なのか是非聞いてみたい。 「>>57 の考え、休むに似たり」
>よってインデックスが正しい。
>>55
>二重にインデックスを張る行為には _全く意味がない_。 >>61
m9(^Д^)プギャー ぜんぜん意味わかってねー。 >いまでも主キー指定での取得になっていて…
これと似た台詞を聞いたことがあるけど、念のため調べてみたら
primary key (項目A, 項目B)の構成のテーブルで
項目Bだけで検索してたというのがあったよ。
大昔のRDBのなかには
a) where 項目A = ? and 項目B = ?
b) where 項目B = ? and 項目A = ?
で索引を使ったり使わなかったりしたのもあったけど最近のは大丈夫ですよね? >>57
想像するに…
・一行ずつ取得ではなく、複数行持ってきてUPDATEはループで回せ。
・UPDATE一発でやれ
のどちらかを言いたいのだと思うけど、それじゃ出来ない処理なんて
いくらでもある。そう言うときの為にストアドがある。
そもそも
「ストアドが存在するDBMSにもかかわらずクライアントでバッチ更新」
なんて仕様が出てくる時点で間違い。
>>63
> 最近のは大丈夫ですよね?
そうでもないよ。 >>64
物事には順序がある。
一行ずつ取得してる新人に、いきなりストアドでやれとは言わない。
ストアドなどという前にやることがあるだろう。 >>65
VBでバッチ処理が書けてストアドだと書けないなんて事があるか
どう考えてもストアドの方が簡単だろう。
単なる怠慢。 ストアドでバッチ処理を書き直したまではいいのだけれど、
数件おきにコミットさせるとカーソルがクローズしてエラーになってしまう。
1件分の処理の間に子レコードの処理も入るのでトランザクションは使いた
いのだが全部処理するには総数が大きい。さてどうするべ、週末なのに・・・ >>67
Oracle で、FOR UPDATE 付きの問い合わせをしてるなら
それは仕様。ROWID 使え。
Oracle じゃないなら知らん。
つか、スレ違い。 >>67
コミット後にカーソルをオープンしたままにする方法はないの?
大抵のDBMSならできるはずだけど。 >>57でキーボードに茶を吹いたよ。 どうしてくれる。
>>64はきっと釈迦のような慈悲の心を持っているんだろうな。 >>70
DB2とかのやり方をまねしちゃだめ。
カーソルループ中にCOMMITする発想はあんましよくない。
途中でこけたら元に戻せなくなる。
そういう場合はロールバックセグメントを大きくとっておくのがOracleのやりかた。
>>74
そうか?ケースバイケースだろ。
カーソルループの中で一部のデータのみコミットされると整合性がとれ
なくなるなケースはおっしゃる通りだが。
カーソルループの中で一部のデータのみコミットされても整合性がとれ
るケースだってないか。
その場合は、カーソルループの中でコミットしたほうがロックの期間
が短くなるし、いいと思うけど。
ロックの期間を短くしたほうがいいっていうのは、どんなDBでも同じ
じゃねーか。 >>77
カーソルループでの更新が途中でこけると、どこまでやったかがわかんないから最初からやり直すことになると思うけど。
このとき、途中までCOMMITしてたらそこまでの更新をもう1回やることになる。
それでも整合性がとれるようなケースってあんましなさそうな気がするけど...
>>78
その通り。
>>77のケースはやろうとすれば出来るだろうけど、
管理が非常に難しくなるし、
どこまでコミットしたかの情報も一々記録しないといけないからパフォーマンスも悪くなる。
そのあたり、セーブポイントでどうにかできないのでしょうか。 そもそもセーブポイントって、どういうものか理解しているのか?
>>78,79
カーソルループの中で整合性が取れるケースって、珍しくはないよ。
いくつか思いつくけどね。
例えば、受注テーブルを基に、物流システムへ渡す出荷指示データ
を作成するバッチ処理とか。
受注テーブルの出荷指示フラグと出荷日を基にカーソルループでまわす
場合。で、ループの中では、受注テーブルの出荷指示フラグを更新し、在庫
テーブル更新、出荷指示テーブル作成とかやってる場合、処理する受注伝票
単位で整合性が取れてれば問題ないというケース。
>管理が非常に難しくなるし、
どこまでコミットしたかの情報も一々記録しないといけないからパフォーマンスも悪くなる。
正直、意味が良くわからん。多分、管理が非常にむずかしくなるってのは、
どこまでコミットしたかを把握したいという意味なんだろうけど。
すでにコミットしたデータは、整合性が取れてるわけだから、基本的には気に
する必要はない。プログラムの不具合で、コミットしたデータの信頼性が損なわれている
場合でも、テーブルに更新時のタイムスタンプと最終更新PGMのIDでも持たせて
おけば、調査できるだろ。
基本的にはバグなんだから、それよりロックの期間が長くなるというデメリット
のほうが俺はいやだね。
>>82
彼らの言っているのは
> ループの中では、受注テーブルの出荷指示フラグを更新し、在庫
> テーブル更新、出荷指示テーブル作成とかやってる場合
この「ループの中」の途中でコミットしてしまうと言うケースを想定して
話をしているんだよ。
「カーソルループ」と言う言葉に捕らわれすぎで話の本質が分かってない。 >>83
そうなのか?だとすると確かにレアケースだが。
67の質問ってそういう意味じゃねーと思うがな。実際、DB2,MSSQL,
Oracleもデフォルトじゃコミットしたら、カーソルクローズしちゃう
しな。(SQL92の仕様だからだろうけど。)
69の回答も俺とおんなじ理解だろ。
話の本質が分かってないのは、お前のほうじゃねーかって気がするがな。 >>84
67に対しては69でFA出てる。
そこから先の話はトランザクション内でのコミットの是非についてだろ。 >>85
>そこから先の話はトランザクション内でのコミットの是非についてだろ。
そんなのまずいに決まってんじゃん。トランザクションの1つの要件は、
整合性を確保できる最小単位であることだ。(原子性、一貫性)
俺が77で言っているのは、カーソルループ1回単位が1トランザクション
の場合と、カーソルループ全体が1トランザクションの場合の話。
>>67に対しては70でFA出てる
やっぱり話の本質が分かってないのは、お前のほうだと思うがな。俺は、
70に対する返答(74)に対して、77で返答してんだから。
どこから、トランザクション内でのコミットの是非についてになったん
だ。 >>87
言ってる意味がさっぱりわからん
とりあえず落ち着け >>88
二段落目読んでも解らないとなるとヤバイ。 そもそも同列に語ることがおかしいってスレでいいんだよな。
・ストアド化による性能向上
ミドルウェア及び通信等のコスト減を目的
・インデックスをきちんとすること
データに対するアクセス経路の最適化を目的 >>90
>>67 以降、違う話に花が咲いています。 >>90
>>91の言うように、話題が変わってます。
カーソルループで大量更新をする場合の話。
>>87,88
想定している状況がそれぞれ違ってるみたいだから
ちょっとこじれかけてるけど、めずらしくまともな議論
に育ちそうだからマターリいこーぜー。
すごい遅レスだが。
>そんなのまずいに決まってんじゃん。トランザクションの1つの要件は、
>整合性を確保できる最小単位であることだ。(原子性、一貫性)
これは、トランザクションは整合性を確保する最小単位だから、
トランザクション内部でのコミットは有り得ないということが
言いたかった。
OracleのSPはネーティブコードではなくインタプリタのようです、
DBの問い合わせではなくロジックをしこたま実行するプログラムを作ったの
ですが予想の百倍ぐらい時間がかかりました。
SPそれ自身の実行速度はVBとたいして変わらない印象です、
サーバに中途半端なCPUを使うとPCでVBのほうが早い可能性も
ありです。 >>94
たいていの処理系ではStored ProcedureはP-Codeのような中間言語方式だから
Oracleもそうじゃないかな。一般的にサーバーサイドでCPUを多く使う処理は
避けたほうがいいから問題ないように思う。複雑な処理をしたいならOracle内臓の
JServer VMでJava stored procedureを使うという手もある。こちらはJITでコンパ
イルされるから2回目以降の処理は速い。 >>94
>OracleのSPはネーティブコードではなくインタプリタのようです
んな事ぁちょっと考えれば解(ry >>94-96
PL/SQLはネイティブコンパイルもできる >>97
そういえばそんなのがありましたね。Cコンパイラが別に必要だったり、
設定がめんどかったり、SQLなどのDBアクセス部分には効果がなかったり
で結局使いませんでした。
>DBの問い合わせではなくロジックをしこたま実行するプログラムを作ったの
こういうのには効果がありそうです。 ここが一番ヘビーユーザーが多いみたいだね
教えて欲しいのだが、行レベルロックに対応しているDBはオラクル
以外にありますか? >>100
いやMSSQLは、テーブルごとロックする
読み取り以外はロック待ち状態になった気がした >>102
はぁ?
SQLServer2000であれば行単位のロックが可能だよ。
あまりにも膨大になってくると、ロックエスカレーションを引き起こし表単位のロックになるがな。
>103
あれって、インデックスが無いと
ページになるんじゃなかったけ?
勘違いかな。 >>104
「テーブルスキャン」と混同してない?
SQLServerは7.0から行ロックをサポートしてるし、Sybaseは11.9.xから。
DB2は知らんけど、今時行ロックサポートしてない商用RDBMSなんて相手に
されないと思うけど。 >>99
おまいはここが質問スレかどうかも解らんのか? 10年ぐらい前なんでよく憶えてないが、DB2も行ロックするよ 運用担当が行ロックをありがたがるのは理解できるのだが、
開発担当が行ロックじゃなきゃ使えないとか言ってるのを聞くと
それは技術力がないという以前の単なるへたれなだけのような気がする。 >ストアドよりインデックスのほうが速いよ (<−−スレタイ)
それぞれ、どのようにした速度が改善されるのかを考えたほうがいい
ストアドによる処理速度の向上は以下の2点による。
1.プログラムがサーバーにあるためサーバークライアント間の
回線経由のデータ転送をなくすことによる速度アップである
2.SQLを中間言語に落とすことにより、インタープリタの必要がない
インデックスによる速度改善とは以下
3.ディスクアクセスを少なくする。
ストアドを使うときの注意事項
4.ストアドはLAN環境だと1.の速度アップは期待できない。低速の
ネットワークならば期待できる。
5.ストアドのプログラムの管理が面倒。デバックしにくいDBもある。
結論を言うと、
6.インデックスによる速度アップはすべきである。
(というか、これをしないと普通は、実運用に耐えられない)
7.ストアドによる速度アップはLAN環境でのC/Sの場合は
期待できない。低速回線経由のC/Sならば期待できる。
8.ロジックを共有するという目的ならばストアドの使用は可。
以上かな。 > 111
あんたが正解。
クエリー投げてカーソル範囲を確定するのに
一番影響するのがインデックスだし、
インデックスをつけても、変わらないのがC/S間の
データ転送速度。(FETCHね)
ストアドなら、ネットワークインフラの性能が
左右するが、クライアントからのちまちました
カーソルFETCHかますより、全レコードを配列変数などで
アウトパラメタとして一括送信したほうが早い場合も
ある。
全て条件付きのケースバイケースだけど、
「クエリを実行してカーソルを確定する」部分と
「カーソルからレコードを取得する」部分の違いは
ちゃんと理解したほうがいいですね。
FETCHしたレコードが大して多くないのに、処理が遅いとかって、
大体クエリの効率が悪く、カーソル処理の場合FETCH − LOOPではなく
その前のクエリ実行が遅かったりする。
そんなときは、いくらストアドにしてもだめ。
SELECT文の実行計画を調べて、その対処としてインデックスを
付与することが明らかであれば、そうすべし。
> ストアドによる速度アップはLAN環境での C/S の場合は期待できない。
これには反論あり。100Mbps の LAN であってもサーバーカーソルを使うと
著しいパフォーマンス低下をもたらす。参照系だけでファイアーホースを
使うならともかく、サーバーカーソルを使ってフェッチ&アップデートを
繰り返すなんて LAN でもやるべきではない。
>>1 はフェッチ&アップデートの多発で速度低下していると言っているのだろう。
その考えは結構正しい。LAN であってもユーザーの判断・操作を
必要としない一括更新はストアドにすべし。クライアントプロセスで
更新する必要性がなかろう。 >>111
ストアドの利点はもう1つあって、それは静的SQL構文であること。
既にコンパイル済みなので、SQL文の構文解析の手間が無いので高速。
あと高速化とは関係無いけど、バグが発生した場合はDBサーバに対して修正するだけで良い。
C/Sシステムほど、その効果が高い。
>>114
愚痴スレだって事に気付かない莫迦がスレ伸ばしてたからね。
で、前の方の書き込み見ずに蒸し返す莫迦がageやがった、と。 >>114
いいえ、的外れなことをそれっぽく言ってみようとするスレです >>114, 116, 117
君たちの見解を知りたいものだ クソスレの有効利用でいいことじゃないか。何を粘着してるんだか。 > 113
DBサーバ上のローカルアクセスならLAN性能は関係ないぞ。
サーバマシン単体の性能なら話はわかるが。
>>120
いや同一ホスト内であってもサーバーカーソルを別プロセスから
動かすってのは、かなりの高コスト処理なのよ。
ADO なんかで MoveNext とかするでしょ。サーバーカーソルの場合
そのたびにサーバーカーソルを動かすためのストアドとかが裏で呼ばれるわけ。 だから、FETCHもサーバ(プロセス)でやって、データを一括で返せば?
SQL Server のストアドは詳しくないが、アウトパラメタで配列
返すことはできたっけ? >>122
SQL Serverの場合は1クエリーで処理できないような問い合わせは
Temptテーブルを仲介させると効率よく処理できる。
table型はストアドの外では使えなかったと思う。 似たような速度の話を一つ。
3000件(5フィールド)のデータがあるとして、
1.ストアド内でカーソルで回して使用
2.最初に配列に取り込みカウンタで回して使用
上の数字は、適当なものだけど、こゆ場合は、どっちが速いの?
カーソルって1レコード分のデータのみメモリにあるのかな?
DBアクセスしてるとしたら、2.のが速そうなんだけど。
だれか分かる人〜
配列にいれると2度手間だからどう考えても遅いよ。
データベースの種類にもよるけど、メモリにあるのはキャッシュされた複数レコード。
SQLをコンパイルしたコードとインデックス位置を保持してるのがカーソル。
読み込みはキャッシュか物理記憶からその情報を元に呼ばれる。 >>127
だーからー…
今頃ノコノコ出てきてアゲてんじゃねーよ間抜け。 (っ´▽`)っ
っていうか、要するに
インデックスとストアドの両方を採用すればいいんじゃね?
って言えばいいんじゃね?
と半年振りに書き込んだ私に誰か拍手してくれよん☆