2

私のプロジェクトでは、大量のデータを返す大規模なクエリを実行しています。このクエリのサイズが原因で、実行時間が 1 分を超える場合があります。これにより発生する可能性のある他の問題を無視して、現在実行中のクエリをキャンセルする方法はありますか?

たとえば、ユーザーがクエリを開始すると、標準の「結果を読み込んでいます...」ページにリダイレクトされます。その後、結果が不要になった場合は、[キャンセル] ボタンをクリックして、実行中のクエリを何らかの形で終了させることができます。

これは可能で、どのように行うことができますか?

ありがとう!

4

3 に答える 3

1

私が知っている唯一の方法は、データベースを再起動することですが、DB のセットアップによっては、キャンセル シグナルを送信できる場合もあります。おそらくrack-timeout gemを見ることができますか?

本当の問題は、クエリにそれほど時間がかからないことです。この方法で問題にアプローチしないことを強くお勧めします。はるかに良い方法は、クエリを調べて最適化を試みることです。合法的に完了までに 1 分以上かかるクエリはほとんどありません。データのダンプをローカル マシンに取得し、クエリで EXPLAIN を実行してボトルネックを見つけます。適切なインデックスを追加することで、142 秒の大規模なクエリを 3 秒未満に減らしたので、同じ効果が得られない場合は驚くでしょう。

于 2013-08-05T20:55:59.933 に答える
1

私は最近、このようなことをしました (アプリケーションに「キャンセル」ボタンを追加しました)。私が一緒にハッキングした plpgsql 関数を以下に示します。これは基本的にpg_cancel_backend()関数のラッパーです。

警告:

1)。アプリケーションは一意の ID (または UUID) を作成し、それを「p_uid」パラメーターとして関数に渡す必要があります。

2)。アプリケーション ユーザーをハードコーディングしました (変更されません)。

3)。Postgresql 9.0+ (これは 9.2 用に作成されたもので、それ以前のバージョンではテストされていません)

4)。関数のセキュリティを少し強化することができます。

CREATE OR REPLACE FUNCTION public.cancel_user_query(p_uid TEXT, OUT retval BOOLEAN) RETURNS boolean
AS $function$
DECLARE
BEGIN
    /*  The pg_sleep() call at the start is because if a user issues a query
        then promptly tries to kill it, it will likely not have shown up in the
        pg_stat_activity view yet (there is a delay before it appears).
        XXX: The GUC setting "track_activities" *MUST* be enabled for this to work.
    */

    retval := FALSE;
    IF ( current_setting('track_activities')::BOOLEAN IS NOT TRUE ) THEN
        RAISE WARNING '[PUBLIC.CANCEL_USER_QUERY] - "track_activities" *MUST* be enabled for this to work';
        RETURN;
    END IF;

    /* In a system under regular high load, this might need to be bumped higher than 2 seconds */
    PERFORM pg_sleep(2); 

    WITH q AS ( SELECT pid FROM pg_stat_activity WHERE LOWER(usename) = 'YOUR_APP_USER' AND application_name = p_uid AND state <> 'idle' )
    SELECT pg_cancel_backend(pid) AS retval
    INTO retval
    FROM q;

    if ( retval IS NOT TRUE ) then
        retval := FALSE;
    end if;

    RETURN;

EXCEPTION
    WHEN others THEN
        RAISE WARNING '[PUBLIC.CANCEL_USER_QUERY] - ERROR: %',sqlerrm;
        retval := FALSE;
        RETURN;
END;
$function$ LANGUAGE plpgsql SECURITY DEFINER;

[クエリのキャンセル] ボタンをクリックすると、アプリケーションは関数を実行し、返されたステータスを確認します。例えば。SELECT retval FROM public.cancel_user_query('asifdaqiwaviafasdf') retval

于 2013-08-05T22:53:24.107 に答える