8

実行時に進行状況メッセージを出力したい SQL スクリプトがあります。SQL ステートメント間でメッセージを出力するのは簡単ですが、非常に長時間実行される INSERT INTO SELECT がいくつかあります。たとえば、1000 行ごと、または 5 秒ごとなど、select ステートメントにメッセージを出力させる方法はありますか?

注: これは SQL Anywhere の場合ですが、どの SQL ダイアレクトでの回答でも問題ありません。

4

12 に答える 12

5

単一のクエリの実行ステータスを取得する方法はありません。主流のデータベース エンジンは、この機能を提供していません。
さらに、進行状況の実装が存在する場合、測定可能なオーバーヘッドが生成されるため、進行状況を表示するためにクエリにすでに不快なほど長い時間がかかっている場合、進行状況を表示することでさらにスローダウンを引き起こすことは、設計目標ではない可能性があります。SQL 実行の進行状況の見積もりに関する
この記事は役に立つかもしれませんが、実際的な意味は限られています。

于 2008-09-24T19:59:34.833 に答える
3

セットベースの操作 (リレーショナル データベースが使用するもの) の進行状況の考え方は、少なくとも進行状況バー (完了した割合と合計) で表示されるほどにはあまり役に立ちません。オプティマイザーが何をする必要があるかを判断し、操作の全コストを実際に理解するまでに、操作の大部分は既に完了しています。進行状況表示は、一連の操作ではなく、反復操作を目的としています。

これは、一般的な SELECT ステートメントの実行について話しています。個別のステートメントである挿入の場合、ステートメントの消費率を監視することにより、サブミッターからそれを行うあらゆる種類の方法があります。それらが一括挿入 (select into、insert from など) である場合は、上で説明したのと同じ問題が実際にあります。セット操作は、プログレス バー タイプの表示をやや無意味にする方法でバッチ処理されます。

于 2008-09-24T19:55:45.327 に答える
3

SQL 自体には、この種のことに対する規定はありません。これを行うには、データベース エンジンと直接やり取りする必要があり、データベース全体で標準的ではありません。

于 2008-09-24T19:49:53.407 に答える
3

私は SQL Anywhere エンジン開発チームに所属していますが、現在これを行う方法がありません。約束はできませんが、この種の機能を将来のリリースに追加することを検討しています。

于 2008-09-24T20:12:02.013 に答える
2

SQLにはこれを直接行う方法がないことに同意します。1 つの方法として、一度に TOP 1000 のみを挿入してから、ステータス メッセージを出力することが考えられます。次に、必要に応じてこれを繰り返します (ある種のループで)。欠点は、自分がどこにいるかを追跡する方法が必要になることです。

このアプローチは、1 つの大きな INSERT を実行するほど効率的ではないことに注意してください。

于 2008-09-24T19:55:16.437 に答える
2

これに対する SQL 標準のソリューションは確かにありません。絶望的な状況で申し訳ありませんが、Oracle、SQL Server、Sybase、または MySQL でこれを行うことができるものを見たことがないので、SQLAnywhere にはあまり期待できません。

于 2008-09-24T19:50:45.450 に答える
2

これが私がすることです(Sybase / SQL Server構文):

DECLARE @total_rows int

SELECT  @total_rows = count(*) 
FROM    Source_Table

WHILE   @total_rows > (SELECT count(*) FROM Target_Table) 
BEGIN
    SET rowcount 1000 

    print 'inserting 1000 rows' 

    INSERT  Target_Table         
    SELECT  * 
    FROM    Source_Table s
    WHERE   NOT EXISTS( SELECT 1 
                        FROM   Target_Table t
                        WHERE  t.id = s.id )
END

set rowcount 0
print 'done'

または、ID に基づいて実行することもできます (ID が数値であると仮定します)。

DECLARE @min_id   int, 
        @max_id   int, 
        @start_id int, 
        @end_id   int

SELECT  @min_id = min(id) , 
        @max_id = max(id) 
FROM    Source_Table

SELECT  @start_id = @min_id , 
        @end_id   = @min_id + 1000 

WHILE   @end_id <= @max_id 
BEGIN

    print 'inserting id range: ' + convert(varchar,@start_id) + ' to ' + convert(varchar,@end_id) 

    INSERT  Target_Table         
    SELECT  * 
    FROM    Source_Table s
    WHERE   id           BETWEEN @start_id AND @end_id

    SELECT  @start_id = @end_id + 1, 
            @end_id   = @end_id + 1000 
END

set rowcount 0
print 'done'
于 2008-10-02T12:13:57.793 に答える
1

別の別のプロセスに、挿入が行われているテーブル内の行数をカウントさせて、それらの何パーセントが既に存在するかを判断することも考えられます。もちろん、これには最終的に合計を知る必要があります。これは、サーバーの負荷についてあまり心配していない場合にのみ、おそらく問題ありません。

于 2008-10-02T01:31:48.307 に答える
0

それが必要な場合、またはあなたが死んだ場合、挿入、更新、削除のために、db変数でいくつかのトリガーロジックを使用でき、SQLを実行して変数データを取得し、ユーザーに進行状況を表示することができます。

使いたくない場合は、例を書いてお送りします。

于 2008-10-02T01:10:14.067 に答える
0

何か他のものを探して、この古いスレッドに出くわしました。集合演算だからといって進行状況の情報が必要ないという考えには同意しません。ユーザーは、待ち時間がどれくらいかを知っていれば、長い待ち時間でも許容できることがよくあります。

これが私が提案するものです:

これを実行するたびに、挿入された行数と合計時間をログに記録し、そのプロセスの最初にステップを追加して、そのログをクエリし、推定合計時間を計算します。前回の実行に基づいて見積もりを行う場合は、処理が完了するまでの待機時間について、許容できる適切な見積もりを提示できるはずです。

于 2014-02-05T21:21:05.040 に答える
0

Toad を使用している場合は、テーブルから一連の INSERT ステートメントを生成し、ユーザー入力の頻度でコミットするように構成できます。スクリプトを少し変更して、新しいデータがどれだけコミットされたかを確認できます。

于 2008-09-24T19:52:03.793 に答える
0

数回の実行のタイミングを計ってから、進行状況バーを平均レコード/秒の速度で進めることで、ユーザーへの影響をシミュレートできます。

唯一の他の方法は

1 - データベース エンジンの API を参照して、そのための準備が整っているかどうかを確認します。

また

2 - INSERT を多くの小さなステートメントに分割し、それらについて報告します。しかし、これはパフォーマンスに重大な悪影響を及ぼします。

于 2008-09-24T20:16:07.790 に答える