簡體   English   中英

Oracle SQL-查詢時間限制

[英]Oracle SQL - Query Time Limit

以類似的方式

select * from mytable where rownum <= 1000;

會給我查詢結果的前1000行,有沒有辦法

select * from mytable where runtime <= 1000;

哪個將返回在運行查詢的前1000個<時間單位>中獲得的結果?

Oracle不支持此功能 ,至少在您的示例中並不容易。

我發現一個博客能夠限制用戶在特定資源組中的執行時間。 他們為上述用戶創建了一個特殊的組,然后他們為該用戶定義了一個資源計划,稱為LIMIT_EXEC_TIME 其代碼如下,以供參考:

set serverout on size 5555
--
-- first remove an existing active plan
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN ='';
--
-- delete any existing plan or group
-- we have to create a pending area first
exec dbms_resource_manager.clear_pending_area();
exec dbms_resource_manager.create_pending_area();
exec dbms_resource_manager.DELETE_PLAN ('LIMIT_EXEC_TIME');
exec dbms_resource_manager.DELETE_CONSUMER_GROUP ('GROUP_WITH_LIMITED_EXEC_TIME');
exec DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA;

exec DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();
begin
  dbms_resource_manager.create_pending_area();
  --
  -- we need a consumer group that maps to the desired oracle user:
  dbms_resource_manager.create_consumer_group(
    CONSUMER_GROUP=>'GROUP_WITH_LIMITED_EXEC_TIME',
    COMMENT=>'This is the consumer group that has limited execution time per statement'
    );
  dbms_resource_manager.set_consumer_group_mapping(
    attribute => DBMS_RESOURCE_MANAGER.ORACLE_USER,
    value => 'PYTHIAN',
    consumer_group =>'GROUP_WITH_LIMITED_EXEC_TIME'
  );

  -- and we need a resource plan:
  dbms_resource_manager.create_plan(
    PLAN=> 'LIMIT_EXEC_TIME',
    COMMENT=>'Kill statement after exceeding total execution time'
  );

  -- now let's create a plan directive for that special user group
  -- the plan will cancel the current SQL if it runs for more than 120 sec
  dbms_resource_manager.create_plan_directive(
    PLAN=> 'LIMIT_EXEC_TIME',
    GROUP_OR_SUBPLAN=>'GROUP_WITH_LIMITED_EXEC_TIME',
    COMMENT=>'Kill statement after exceeding total execution time',
    SWITCH_GROUP=>'CANCEL_SQL',
    SWITCH_TIME=>15,
    SWITCH_ESTIMATE=>false
  );

  dbms_resource_manager.create_plan_directive(
    PLAN=> 'LIMIT_EXEC_TIME',
    GROUP_OR_SUBPLAN=>'OTHER_GROUPS',
    COMMENT=>'leave others alone',
    CPU_P1=>100
  );

  DBMS_RESOURCE_MANAGER.VALIDATE_PENDING_AREA;

  DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA();

end;
/

exec dbms_resource_manager_privs.grant_switch_consumer_group('PYTHIAN','GROUP_WITH_LIMITED_EXEC_TIME',false);

exec dbms_resource_manager.set_initial_consumer_group('PYTHIAN','GROUP_WITH_LIMITED_EXEC_TIME');

select * from DBA_RSRC_CONSUMER_GROUPS;
select * from DBA_RSRC_GROUP_MAPPINGS;
select * from DBA_RSRC_PLANS;
select * from DBA_RSRC_PLAN_DIRECTIVES;

-- to enable it:
ALTER SYSTEM SET RESOURCE_MANAGER_PLAN ='LIMIT_EXEC_TIME';

SELECT se.sid sess_id, co.name consumer_group,
 se.state, se.consumed_cpu_time cpu_time, se.cpu_wait_time, se.queued_time
 FROM v$rsrc_session_info se, v$rsrc_consumer_group co
 WHERE se.current_consumer_group_id = co.id;

select username,resource_CONSUMER_GROUP,count(*) from v$session group by username,resource_CONSUMER_GROUP;

部分結果

查詢可以返回部分結果,但查詢還會引發異常“ ORA-00040:超出活動時間限制-調用已中止”,客戶端必須忽略該異常。

這可以通過執行大量CPU工作的函數來模擬:

create or replace function sleep_cpu return number authid current_user is
    v_loop number := 0;
begin
    for i in 1 .. 10000000 loop
        v_loop := v_loop + 1;
    end loop;

    return v_loop;
end;
/

SQL * Plus可以證明客戶端能夠讀取部分結果:

SQL> set timing on
SQL> select sleep_cpu()
  2  from dual
  3  connect by level <= 100;

SLEEP_CPU()
-----------
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
   10000000
ERROR:
ORA-00040: active time limit exceeded - call aborted


15 rows selected.

Elapsed: 00:00:08.52
SQL> 

請注意,在此示例中,經過時間為8秒。 我將超時設置為5秒,這表明很難獲得良好的精度。

CPU時間,未用時間

資源管理器僅計算CPU時間,而不計算經過時間。 盡管有文檔說明,但是這是正確的。 Pythian文章中的評論之一表明,可以使用ALTER SYSTEM SET EVENT = '10720 trace name context forever, level 16384' scope=spfile;來更改此行為ALTER SYSTEM SET EVENT = '10720 trace name context forever, level 16384' scope=spfile; (和重新啟動),但這對我不起作用。

例如,創建以下函數:

create or replace function sleep_no_cpu return number authid current_user is
begin
    execute immediate 'begin dbms_lock.sleep(1); end;';
    return 1;
end;
/

此SELECT將運行整個100秒,因為它沒有使用100秒的CPU。

select sleep_cpu()
from dual
connect by level <= 100;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM