こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

SELECT と INSERT の速度

素人な質問ですみません。

環境:ORACLE 10g

ストアドである値をINSERTする場合、
キー重複でEXCEPRIONに飛ばすのと、SELECTで同キーの件数(0 or 1)を取得して、
O件の場合のみ処理を行うのではどちらのほうが速度は上なのでしょう?

ちなみに登録されるテーブルのレイアウトは、
項目(1)NUMBER(8)   PK,
項目(2)NUMBER(8)   PK,
項目(3)VARCHAR2(256) PK,
項目(4)NUMBER(2)   PK,
項目(5)NUMBER(8)
って感じです。

よろしくおねがいします。

投稿日時 - 2007-04-12 13:07:25

QNo.2915024

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

3人が「このQ&Aが役に立った」と投票しています

回答(6)

ANo.6

質問者様のバッチ処理での状況を見ますと、私が過去に性能改善を行ったシステムと同じような要件と思われます。
その時もバッチ処理で、約7万件のデータを毎回DBに格納する際、既に存在するレコードが数件ありました。
その時の性能として、改善前はSELECTして、レコードの有無を調べ、レコードが既に存在してればUPDATE、なければINSERTするというような感じで作られていました。
この処理時間は1時間半でした

これを無条件にINSERTして、Exceptionが発生したらUPDATEに切り替えるという処理に直したところ、処理時間が30分になりました。

ですので、質問者様の条件の際には
(1)いきなりINSERT
(2)Exceptionが発生したらUPDATEに切り替える
というやり方を経験的に推進します。

Oracle8 PL/SQLでした。

投稿日時 - 2007-04-19 12:43:57

ANo.5

あ、ごめんなさい。
ANo.4でなんかトンチンカンか回答をしてしまいました。

重複って、テーブル内のデータと、これから登録するデータのことですよね。

下半分の件も、バッチならば処理の最初にテーブルロックしちゃいますよね。

ANo.4とこの文章は、無視してください。ごめんなさい。

投稿日時 - 2007-04-14 12:30:19

ANo.4

回答へのコメントで「同キーのデータが1~2レコード存在すると思われます。」がちょっと気になります。
PK張ってあるのに重複レコードがあるの?

あと、(1)select+insertより(2)insertが早いとのことですが、
insertする場合、暗黙のテーブルロックがかかるため、
このテーブルにロックが必要な処理(update,delete含む)が非常に多いと見積もれる場合、ロックの競合を避けレスポンスを維持するため、
(1)の方法をとる場合があります。

投稿日時 - 2007-04-14 12:21:16

ANo.3

前者の方が必ず速くなります。
というのも後者の方法はselectで重複が無いかをチェックした気になっているのは人間だけでOracleにとっちゃあそんなことは一切関係無く、
プライマリキーがあるのですから再度INSERTするときに重複チェックを必ず行います。
つまりSELECTでの重複チェックは全く意味が無い負荷をかけるだけの処理なのです。
プライマリキーの重複などチェックがOracleに任せられるのであれば任せるべきです。
後者の方法やmerge文を用いるのはプライマリキー制約などではない、
DBに定義していないチェックをしたい場合に限られます。

投稿日時 - 2007-04-14 03:40:32

ANo.2

merge文なんてものもあります。一概には言えません。実測されるのが一番でしょう。

insertでもキーを検索(select)していることは変わりませんので、
直接insertでexceptionを返すのが早いか、selectの結果を返すのが早いかということになります。この2つが同じ速度だと仮定すると、直接insertの場合には、うまくいけば、exceptionが発生しない場合もあるので、その場合には、その後の1sql分の短縮が見込めることになりますね。あとは、insertで重複する確率の問題になるかと思います。

実際にストアドで簡単に計測してみた方がよいと思いますよ。

投稿日時 - 2007-04-12 22:27:02

ANo.1

トランザクション系の処理でしょうか、それともバッチ処理でしょうか?また、母体件数と重複キーになる可能性(確率)がどれくらいかによって変わります。
また、求められる性能要件によっても重要性が変わってくると思いますが。。。

単純に考えると、select<insert<select後insert の処理速度になりますよね!
insert結果のexceptionルーチンでの処理も、count=0の場合の処理も同一と考えると、
母体数が多い、もしくは重複する確率が低い場合、insert<select→insert
母体数が少ない、もしくは重複する確率が高い場合、insert>select→insert
になると想定されます。
バッファサイズやselectするキーの内容によって、ヒット率も変わって来ますので、一概には言えませんが、可能であれば、sqlトレースや実行計画を取得して、最適なチューニングを施した方がいいと思います。

投稿日時 - 2007-04-12 13:38:06

お礼

ご回答ありがとうございます。
バッチ処理です。
おそらく母体数が5万~40万ほどで、
同キーのデータが1~2レコード存在すると思われます。
なんとなくinsert<select→insertの予感がします。

投稿日時 - 2007-04-12 14:25:08

あなたにオススメの質問