• ベストアンサー

処理速度について(UPDATE)

下記の2つのSQL句があります。 どのSQLが処理速度が速いのでしょうか。 また、一般的なのはどのSQLなのでしょうか。 処理1 UPDATE テーブルA SET 項目A = '0' WHERE NVL(項目A,'0') = '0'; 処理2 UPDATE テーブルA SET 項目A = '0' WHERE 項目A IS NULL; 私としては、処理2の方が早いような気がするのですが・・・ 教えてください。お願いします。

  • Oracle
  • 回答数5
  • ありがとう数5

質問者が選んだベストアンサー

  • ベストアンサー
  • entree
  • ベストアンサー率55% (405/735)
回答No.4

歴然とした差はないでしょうが、NVL(項目A,'0') に関数インデックスが張られていない限り、処理2の方が高速になるでしょう。 まず、処理1も処理2も全表走査になりますので、実行計画には差がありません。 解析時間については、NVL(項目A,'0') に関数インデックスが存在するかどうかを調査する時間を考慮すると処理2の方が速いかもしれません。(ミリ秒レベルの差もあるかどうかは分かりませんが) 次に、更新量ですが、処理1の場合、項目Aが NULL の場合だけでなく、'0' の場合も更新対象になってしまうため、項目Aが '0' であるレコードが多い場合は若干遅くなるかもしれません。(これはミリ秒の世界でしょうが) さらに、処理1の場合は、項目Aの全ての行に対して NVL 関数を適用しなければならないのに対して、処理2では、単純に項目Aが NULL であるかどうかを比較するだけで済んでしまいます。(これもミリ秒の世界でしょうが)

tyurajima
質問者

お礼

回答、ありがとうございます。 処理2の方が効率的ですが、その差はわずかしかない という事がわかりました。 更新量はそんなにない(せいぜい10万件)ので、 他のPGMと同じように処理1で作業を進めたいと思います。

その他の回答 (4)

  • rename
  • ベストアンサー率33% (2/6)
回答No.5

まず、インデックスですが、 テーブルAの項目Aにインデックスがはってあっても、 この両SQLともインデックスは使用されません。 ですので、処理レコード数が そんなに多くない場合はたいして処理速度は変わらないです。 また、 「WHERE NVL(項目A,'0') = '0'」  と 「WHERE 項目A IS NULL」 の速度を比較する指標値というのは存在しません。 本当にどちらが早いかを知るには、 実際にデータを用意しスクリプトをかまして時間を測定するのが 手っ取り早いです。 数千万件のデータを用意して試すと 少しは違いが出てくるかと思います。 (何ミリ秒程度の違いだと思いますが)

tyurajima
質問者

お礼

回答、ありがとうございます。 処理2の方が効率的ですが、その差はわずかしかない という事がわかりました。 更新量はそんなにない(せいぜい10万件)ので、 他のPGMと同じように処理1で作業を進めたいと思います。 (レスポンスにシビアではない業種なので(笑))

回答No.3

処理1のケースでは、ファンクション索引が ”NVL(項目A,'0')"対して存在するなら 索引検索されますが、そうでなければ、全表検索。 処理2は、たぶん全表検索。 結局、全表検索同士であるなら、nvl関数の微妙なオーバーヘッドだけの 違いでしかないように思います。 実行計画で比較してみてください。

tyurajima
質問者

お礼

回答、ありがとうございます。 処理2の方が効率的ですが、その差はわずかしかない という事がわかりました。 他のPGMを見るとこのシステムでは処理1を使っているので、 この方法で作業を進めたいと思います。

回答No.2

#1のかたへ null 及び 左辺に関数を用いている場合、一切の索引は適用されません。 この場合、実データ件数にもよりますので、実行計画を取得されて検討するのが一番と思います。

tyurajima
質問者

お礼

回答、ありがとうございます。 処理2の方が効率的ですが、その差はわずかしかない という事がわかりました。 他のPGMを見るとこのシステムでは処理1を使っているので、 この方法で作業を進めたいと思います。

回答No.1

処理2の方が私も効率よく処理が出来ると思います。 処理1では、項目Aをnull と 0の場合nvlで変換している為、通常のインデックスを使用しないと思います。 (インデックスでNVL(項目A,'0') を作成していれば使えると思います。) 処理2では is null を使用しているので、null項目をインデックスから取得していると思いますので、こちらが効率的だと思います。 また、更新件数も変わってきます。 (処理1の方が更新件数多) 間違っていれば、誰かフォローください。

tyurajima
質問者

お礼

回答、ありがとうございます。 処理2の方が効率的ですが、その差はわずかしかない という事がわかりました。 他のPGMを見るとこのシステムでは処理1を使っているので、 この方法で作業を進めたいと思います。

関連するQ&A

  • 1テーブル&複数レコードの更新に対して1度のupdate文での処理方法

    1テーブル&複数レコードの更新に対して1度のupdate文での処理方法 Delphi2010+SQL SERVER 2005で開発しています。 update文で、 現在下のようにwhileで複数レコードに対して、 1回、1回、sqlを発行して、更新しています。 これを、一度のSQLの発行で処理できないものでしょうか? 更新テーブルは1つで、更新する項目も同じです。 更新するデータと、where句の条件が異なります。 もし可能なようでしたら、どうかご教授お願いします。 update table set A=1,B=2 where id=1 update table set A=2,B=3 where id=5 update table set A=9,B=99 where id=7 update table set A=5,B=10 where id=15 update table set A=1,B=10 where id=75

  • ORACLEのUPDATE処理

    お世話になります。 UPDATE文のSET句からストアドファンクションを呼び返却値を設定する処理を行っています。 が、以下のエラーが出ます。 「ORA-04091: 表xx.xxxは変更しています。トリガー/関数は見ることができません」 テーブルにトリガーは使用していません。 ストアドファンクション内で、コール側のUPDATEするTABLEを参照(SELECT)しているのですが この箇所を削除すると、エラー発生しません。 以下のような処理です。 UPDATE TABLE_A SET COL_A = FUNC(KEY1,KEY2); FUNC(PKEY1,PKEY2) IS CORSOR C1 IS SELECT COL_B FROM TABLE_A WHERE KEY1 = PKEY1 AND KEY2 = PKEY2; BEGIN ・・・ END; UPDATEですが、自TABLEのSELECTは ・SET句の中でSELECTする場合はうまくいく ・引数渡し→ストアドファンクション内でSELECTはできない という事なのでしょうか。 よろしくお願いします。

  • UPDATEが動いたり止まったり…

    SQLServer2000SP4の環境で、 夜間バッチ処理で update テーブルA set 項目A1 = (select 項目B1 from テーブルB where 項目B2 = 項目A2) where 項目A2 in( select 項目A2 from テーブルA left outer join テーブルB on 項目A2 = 項目B2 where 項目A1 <> 項目B1 ) という処理で、テーブルAとテーブルBの項目1という値が違うものだけ対象にして、テーブルBの項目1をテーブルAの項目1にセットしています。 この処理で正常に終わることがほとんどなのですが、月に2度程、このコマンドのまま停止した状態(エラーなし。コマンドタイムアウトは0にしています)になることがあります。 きっかけとしては、テーブルAのA1にインデックスを設けたということがあり、エラー対策としてインデックスデフラグを処理直前にかけていました。いっときは正常に動いていたのですが、また停止したので、インデックスフラグメントが原因ではなさそうです。(ちなみにこのUPDATEで更新される件数は数十件です) テーブルA:100万レコード程 主キー:項目A2 インデックス:項目A1 テーブルB:100万レコード程 主キー:項目B2 エラーメッセージも何もでなくて、処理が継続中のような状態で止まっているのでこのUPDATE一文でインデックス更新にロックが掛かっているのかなと勝手に想定はしておりますが、どなたか原因と回避を教えていただきたく質問させて頂きました。よろしくお願いいたします。

  • UPDATE文(副問合せ?)について

    うまく説明できないのですが、下記のようなテーブルがあります。 テーブル名:A 項目: A1 A2 A3 A4 AテーブルのA1項目に「5」がセットされているデータについて、 A2に123、A3に321をセットしたいのです。 うまくいかない例ですが、下記のようなイメージです。 UPDATE A set A2=123,A3=321 FROM (SELECT * FROM A WHERE A1 = '5') ちなみに下の書き方はダメです。 「SELECT * FROM A WHERE A1 = 5」の部分は、必ず使用し、変更不可です。 × UPDATE A set A2=123,A3=321 WHERE A1 IN(SELECT A1 FROM A WHERE A1 = 5) 変な質問ですいませんが、何か方法があるのでしょうか。 よろしくお願いします。

  • updateしてもSQLを終了すると元に戻る

    Oracle_9→access2002 で外注開発されたシステムを利用しています さて、Oracle、SQL_Plusの[update TABLE1 SET FIELD1 = 'X' WHERE FIELD1 IS NULL]等でデータ更新後、[select 列名リスト FROM TABLE1 WHERE 検索条件]で確認すると確かに更新されているが、SQLを終了後、再起動すると元に戻ってしまいますが、どんな原因が考えられますか?update実行後に確定操作等あるのですか? Oracleはまったく初心者ですがお願いします

  • UPDATE文で発生するデッドロックについて、教えてください。

    はじめまして。 SQL SERVER初心者の為、ご指導の程お願いいたします。 UPDATE文で発生するデッドロックについて教えてください。 現在、ストアドプロシージャ内で、 以下のUPDATE文を使用しています。 UPDATE テーブルA SET 更新済フラグ = '1' WHERE ロック時間 =パラメータ.ロック時間 AND ロックユーザー = パラメータ.ロックユーザー AND ID = パラメータ.ID ※Where句に使用する、ロック時間・ロックユーザー・IDは、  キー項目では無く、インデックスも使用しておりません。  ただし、対象データを一意に識別できる項目ではあります。   このストアドを含む処理を、ほぼ同時実行すると このUPDATE文で「LOCK TIMEOUT」が発生し、 デッドロックとなってしまいます。 UPDATEの対象となるデータ件数は、ともに500~600件です また、対策としましてロックのヒント文を下記のように設定し、 WHERE句に設定している、ロック時間・ロックユーザー・IDに 対して、インデックスを作成してみましたが、 同様に、デッドロックが発生してしまいます。 UPDATE テーブルA (with rowlock) SET 更新済フラグ = '1' WHERE ロック時間 = パラメータ.ロック時間 AND ロックユーザー = パラメータ.ロックユーザー AND ID = パラメータ.ID SQL Serverに詳しい方、お力になっていただければ、光栄です。 よろしくお願いいたします。

  • updateで

    条件2つの場合updateがエラーになるのですが 下記SQLではだめなのでしょうか。 table_AのAdd=table_B.Add で table_B.name=3 の時 table_A.name=2 UPDATE table_A SET table_A.name=2 WHERE  table_A.Add=table_B.Add AND  table_B.name=3 ->Error

  • SQLでの変数の扱いについて

    VBを利用してのSQL文に変数を使いたいのですが記述方法が良くわかりません。 まず dim a as string dim b as integer dim c as integer a="AAAA" b=10 c=23500 として テーブルZの項目1が nvarchar 項目2が tinyint 項目3がrealであった場合 sql文の記述方法をWebで探していると 文字列変数ならシングルクォーテーションでくくって代入 数値変数ならダイレクトに代入というようにとれるところがあったので下記の 様に記述すると更新されません sqlstr=("UPDATE テーブルZ set 項目1='a',項目2=b,項目3=c where 項目=1") 下記のように分割してそれぞれひとつづつのテストすると更新できます sqlstr=("UPDATE テーブルZ set 項目1=" & a & " where 項目=1") sqlstr=("UPDATE テーブルZ set 項目2='" & b & "' where 項目=1") sqlstr=("UPDATE テーブルZ set 項目2='" & c & "' where 項目=1") 上記の要領で1つにまとめると出来ないので,どのように書けばよいのでしょうか よろしくお願い致します

  • IS NULL

    いつもお世話になっています。 PL/SQLでストアドを作成中なのですが、 あるUPDATE分のWHERE句の条件として“IS NULL”を使用したいのですが、監督者から “IS NULL”はNGという指示が出てしまい困っています。 (理由はNULLは索引の対照外だからということです。) 以前、“IS NOT NULL”の代用として、“項目名 ≧ 0”が使えることを学んだのですが、“IS NULL”にも同じように代用できる条件の記述方法はありますか? “IS NOT NULL”が“項目名 ≧ 0”なら “IS NULL”は“項目名 < 0”というのは無謀でしょうか?

  • SQLのWHERE句を条件によって追加したい

    SQLのWHERE句にパラメータで渡された値がnullでない場合は条件に 含めるようにしたいのですが、書き方が分かりません。 CASEを使って書いてもエラーになってしまいます。 SELECT 項目1 ,項目2 FROM テーブル WHERE 条件1 = パラメータ1 AND 条件2 = パラメータ2 -- パラメータ3がnullでない場合は下記条件を付けたい AND 条件3 = パラメータ3 使っているのはpostgresqlです。 よろしくお願いします。