【先着1,000名様!】1,000円分をプレゼント!

お世話になります

SQL Serverで、
100万件のレコードを削除したいのですが
どのような方法が効率よいでしょうか

また、メモリ負荷など、クライアント側から分かるような実行計画とかは
ありませんでしょうか?

1.100万件を1回でdelete
2.100万件を複数回に分けてdelete
3.100万件を1行ずつキー指定でdelete(deleteを100万回実行)

100万件deleteしてる場合も、他処理でレコードが登録、更新される可能性が高いため、
そちらの処理がタイムアウトなどのエラーにならないようにしたいです

詳しい方に聞いたところ、
delete発行する際に、メモリにアクセスしてるので、
3だとそれが単純計算で100万倍になるので、負荷が高いのでは?
という事でした。

ご教授の程、よろしくお願い致します

このQ&Aに関連する最新のQ&A

A 回答 (3件)

元データの件数はどのくらい?


2000万行あるうちの100万行と、101万行のうちの100万行だと違う方法がありそう。
    • good
    • 1

ローカル処理ではないということで、3ですが20msに一回実行して2日少しでdeleteしたいですね。

    • good
    • 0

もちろん、1回で実行した方が効率は良いです。


処理の1回毎にSQL構文解析→実行計画→実行という動作を行いますし、その都度にメモリやHDDもアクセスすることはあります。できるだけ処理は少ない方が良いです。

>100万件deleteしてる場合も、他処理でレコードが登録、更新される可能性が高いため、
ファントムリードにならないようにきっちりと専有ロックをかけた方が良いです。
で、他処理にはある程度の時間的余裕をもたせられるとベストなのですが。

まあ、その100万件の主キーが何でインデックスがどれくらいあって制約がどのように作られているか、項目数がいくつなのかもわからないので一般論です。
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qトランザクションログを出力せずにデータを削除する方法

大量(30万件程)のデータを削除したいのですが、ロールバックする必要がないのでトランザクションログを出力したくありません。一部のデータは残す必要があるので、トランケートはできないのですが、なにか良い方法はご教授ください。

Aベストアンサー

大量削除の前に、レコード数の全体件数が重要です。
(例えば 100万レコード超なのか30万+α程度なのか)

代表的な手法としては

件数が少ない場合
・ファイル書き出し(CSVなど)をして TRUNCATE 後
SQL loader(directモード)で再度取り込む

・ワークテーブルで同様な事をする。

件数が多い場合
・Data pumpアクセスドライバ経由で外部表を作成
CREATE TABLE ~ TYPE oracle_datapump ~ as select ~
または、CSVから外部表を作成する

・TRUNCATE
・ダイレクトパスインサートで復旧
INSERT /*+ APPEND */ INTO to_table SELECT * FROM from_table ~

となります。

細かな作業は、マニュアル等で調べてください。

Q大量のレコードを削除する方法

約100万件のレコードを削除したいのですが、
一気に削除するとDeviceがいっぱいとなり、問題です。
なので、1000件単位で削除できればと思うのですが、
何度も同じコマンドを送るのも気が遠くなるので、
なんとか自動化にしたいのですか、
簡単に1000件づつ、例えばfor文などを使って、自動的に削除していってくれるスクリプト(SQL文)を教えてください。  ちなみに今はSybaseですが、どんなデータベースでもかまいません。

Aベストアンサー

繰り返し同じコマンドを実行する方法として、isqlの場合は、
go の後に数字をいれることで、コマンドを繰り返し実行できます.
例えば
insert table values ( 1 )
go 10
と指定すると、insert 文を10回繰り返し実行します。

また、set rowcount を使用すると、この後実行されるSQLの対象件数を指定することができます。
例えば
set rowcount 1000
Select * from Table
とすれば1000件が検索されます。
同じように
set rowcount 1000
Delete Table
とやれば100件、削除されるはずです。

ループを使用したい場合 While 文を使います.
前述のset rowcount とあわせて使うといいかもしれません。
set rowcount 1000
declare @count int
select @count = 0
while @count < 100
begin
delete Table [where条件]
select @count = @count + 1
end
削除の対象となる条件がしていされていないので、テーブル先頭の方から適当に1000件消えてしまいます.
実際に作業される際は条件を指定する必要があると思います.

また、Device がいっぱいになるとのことですが、トランザクションログ用のデバイスのことでいいですよね。
上記の方法では、いずれにせよトランザクションログはいっぱいになってしまうと思います.Dump tran 等で適宜対処する必要があるでしょう。

残したい行の条件が指定できるのであれば、 select into コマンドで
別テーブルに残したい行を移動し、元のテーブルを trancate table で削除、テーブルをリネームするのがいいと思います。select into や truncate table は大量にトランザクションログを出さないはずなので何度もコマンドを発行するよりいいと思います.

実際に処理を実行される場合は、必要なデータまで消さないように十分注意して行ってくださいね。
各コマンドの詳細はマニュアルを確認してください。
PDFのマニュアルのURLを参考URLに記入しておきます。

以上、がんばってください。

参考URL:http://www.sybase.co.jp/product/manuals/index.html

繰り返し同じコマンドを実行する方法として、isqlの場合は、
go の後に数字をいれることで、コマンドを繰り返し実行できます.
例えば
insert table values ( 1 )
go 10
と指定すると、insert 文を10回繰り返し実行します。

また、set rowcount を使用すると、この後実行されるSQLの対象件数を指定することができます。
例えば
set rowcount 1000
Select * from Table
とすれば1000件が検索されます。
同じように
set rowcount 1000
Delete Table
とやれば100件、削除されるはずです。

...続きを読む

QEXISTSを使ったDELETE文

「SELECT文の件数」と、
「同じSELECT文を使ったDELETE文の件数」が一致しない現象が起き、困っています。

【SELECT文】※2件返ってきます。
SELECT
  a.部署コード,
  a.社員コード
FROM
  社員マスタ a,
  組織マスタ b
WHERE
  a.部署コード = b.部署コード


【DELETE文】※50件 DELETEされます。
DELETE TABLE
  社員マスタ
WHERE
  EXISTS
  (
  SELECT
    a.部署コード,
    a.社員コード
  FROM
    社員マスタ a,
    組織マスタ b
  WHERE
    a.部署コード = b.部署コード
  )


環境はSQLSERVER2005です。
件数はSQLSERVER2005のカウントオプションで表示されているものなので間違いないです。

宜しくお願いします。

Aベストアンサー

EXISTS 句は、副問い合わせが行を返した場合 TRUE そうでない場合 FALSE と評価されます。

例示いただいた副問い合わせは TRUE を返すので DELETE されます。

詳細については、SQLの入門書を参考にしてください。

Q大量レコードをTRUNCATEせずにすばやく削除する方法

大量レコードをTRUNCATEせずにすばやく削除する方法


100万レコードあるテーブルのうち1万レコードを残して削除したい。TRUNCATEではWHERE句が指定できないので不可。DELETEでは遅すぎる。何かいい方法はないでしょうか?

1万レコードを一時テーブルに退避してTRUNCATE後に1万レコードをINSERTというのは無しです。1万レコードが1秒でもテーブル上から消えてはいけません。

Oracle10g

Aベストアンサー

残したいデータ(レコード)に共通点があれば可能です。
予めパーティションテーブルとしておいて、
残したいデータのみを挿入するパーティションとそれ以外のパーティション定義とします。
パーティションレベルでのTRUNCATEやDROPであれば一瞬でできますし、
必要としている1万行が消えることも一切ありません。

ただし、EEのオプションとなりますが。
EEを買っていないのであれば各パーティションに相当するテーブルを作って
テーブルとテーブルをUNIONするVIEWを作る形になります。

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

QSQLServerでの切り上げ処理

SQLServerで、小数部の丸め処理で困っています。

切り捨て → round(150.7, 0, 1)
四捨五入 → round(150.7)

というところまではなんとかわかったのですが、切り上げ処理がうまくいきません。

ceiling(150.7)やfloor(150.7)などいろいろ試してみたのですが、どうしてもうまくいきません(T-T)

どなたかわかる方がいらっしゃいましたらアドバイスお願いします。

Aベストアンサー

s_husky です。

select ID, (round(round(数量 + (0.99) * sign(数量), 2),0,1)) from table1;

負の値については考慮していませんでした!
面目ありません!

QSYSユーザーでログインしたい

SQL plusでSYSユーザーでログインするにはどうすればよいのでしょうか?
SYSTEMユーザーやSCOTTユーザーではログインできるのですが、SYSユーザーになる方法がわかりません。
お願いします。

Aベストアンサー

>SQL plusでSYSユーザーでログインするにはどうすればよいのでしょうか?
特別なことする必要がないと思います。
ログインできない場合いろいろな原因が考えられます。
一番可能な原因は設定によってSYSユーザーNOMAL権限でログインできない場合あります。
この場合
sqlplus sys/パスワード@接続文字列 as sysdba
で試してください。


>SYSTEMユーザーやSCOTTユーザーではログインできるのですが、SYSユーザーになる方法がわかりません。
conn sys/パスワード@接続文字列 as sysdba

QCloseとDisposeの違い

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。

これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。

そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。

ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。

わけわからなくなってきました。。。

ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。

ここで4つの仮説を立ててみました。

1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる

2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

3. 呼び出し方ではなく、別の要因が存在する

4. 併記する必要がある場合がある

Me.Close()
Me.Dispose()

または、

Me.Dispose()
Me.Close()



どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、...続きを読む

Aベストアンサー

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。
Me.Close() に変えるとうまくいきました。

通常はどちらでもうまくいきます。

>2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

ShowDialogの場合は、メソッド内部で、ハンドルが破棄されているため、Close()メソッドの際にDispose()メソッドが呼び出されます。

>3. 呼び出し方ではなく、別の要因が存在する

そう思います。

>4. 併記する必要がある場合がある

インスタンスを明示的に破棄したほうがよい場合は多く存在します。
Disposeが使えるメンバはIDisposableをインターフェースとして持っているメンバです。
これらのメンバは、外部とのやり取りを行うものが多くあります。
たとえばSQLClientに含まれるようなメンバです。

外部とのコネクションを確実に破棄を保障してほしいなどという場合がありますよね、このようなときに使用します。

Using構文を使用するのとまったく同じ理由になります。
正確にはUsing構文を使用できるメンバには条件があります、IDisposableをインターフェースとして持っているメンバに限るというものです。

ほかにもガーベージコレクタによるファイナライズを伴うかどうかという違いがあります。
Disposeの場合はファイナライズが同時に行われるため、使用していたメモリ空間を開放することができます。

上記のような理由により、
Me.Close()
Me.Dispose()
は両方書いたほうがよいと思います。

蛇足ですが、
Me.Dispose()
Me.Close()
はエラーになります。
Me.Dispose()により、Me本体(インスタンス)は削除されてしまいます。
存在しないMeに対してCloseメソッドを要求することはできないためです。

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリ...続きを読む

Q【SQLServer】IS NULLのパフォーマンス

お世話になっております。SQLSERVER初心者です。

NULLを含む列COL1を検索条件に入れる場合、
パフォーマンスの観点から

WHERE COL1 IS NULL とするのではなく
WHERE ISNULL(COL1,'') = '' とするよう有識者から言われました。

そこで質問なのですが、

(1)IS NULL は基本的に上記のように変換したほうが早くなるのですか?
(2)COL1にもしインデックスが設定されていたとしても、上記の場合だとどちらも効かないですよね?

詳しい方おしえてください。
よろしくおねがいします。

Aベストアンサー

試しにこちらの適当なテーブルに索引をつけて検索してみました。

(1)WHERE COL1 IS NULL
INDEX SEEKになりました

(2)WHERE ISNULL(COL1,'') = ''
INDEX SCANになりました

INDEX SEEKなので(1)の方が効率がよさそうです。
ManagementStudioでSQL実行時に「実際の実行プランを含める」のオプションつきで実行してみてください。

でも、(2)は長さ0の空文字も対象にするから(1)と(2)は結果が変りますよね。このことを考慮してますか?

※長さ0の文字列とNULLを区別するかどうかはDBによって異なります。

Q別のDBからテーブルをコピーする方法

SQL Server2005 Express Edition を使っています。
異なるDB間(同じコンピュータ内)で、テーブルをコピーしたいの
ですが・・・
コピー元DB名:DB_A
コピー元テーブル名:dbo.顧客
コピー先DB名:DB_B

テーブルのコピーは select * into ・・・ from ・・・ を使えばできそうですが、別DBの場合の方法がわかりません。
お教えいただければ幸いです。
よろしくお願いいたします。

Aベストアンサー

別のDBでも同じインスタンス内ならば同じです。

SELECT * INTO DB_B.dbo.顧客 FROM DB_A.dbo.顧客


人気Q&Aランキング