2017-04-20 260 views
3

以類似的方式來的Oracle SQL - 查詢時間限制

select * from mytable where rownum <= 1000; 

將如何給我的第1000行的查詢結果的,是有辦法

select * from mytable where runtime <= 1000; 

這將返回運行查詢的第一個1000 <時間單元中獲得的結果?

+1

我想不出一種方法,我認爲這沒什麼意義。什麼是用例? – BobC

+0

你是什麼意思「什麼是用例?」?!?!?用例是我想在給定的時間內檢索我的查詢的一些結果......你可能會問爲什麼'rownum <= n'的用例,你可以運行整個查詢並忽略除第一個'n'行之外的結果! – Apollys

+1

前N種查詢通常具有有效的業務案例。例如,按銷售量給我排名前1000的銷售人員。我無法想象一個有效的業務案例,其結果是基於查詢需要多長時間。在很多情況下,結果集被確定爲「整體」。 – BobC

回答

1

Oracle does not support this,至少不像你的例子那樣容易理解。

One blog我發現能夠限制用戶在他們所做的某個資源組中的執行時間。他們爲所述用戶創建了一個特殊組,然後他們爲該用戶定義了他們稱爲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:活動時間超出限制 - 呼叫中止」,但必須被客戶忽略。

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> 

注意經過的時間

這可以用做了很多CPU工作的功能來模擬在這個例子中是8秒。我將超時設置爲5秒,這表明很難獲得良好的精度。

CPU時間,不經過時間的

資源管理器只計算CPU時間,不經過時間。儘管文檔說明了這一點。 Pythian文章中的一條評論表明,這種行爲可以通過ALTER SYSTEM SET EVENT = '10720 trace name context forever, level 16384' scope=spfile;(以及重新啓動)進行更改,但這對我無效。因爲它不使用CPU 100秒

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將整個百秒運行:

例如,創建此功能。

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

我也看到了這個頁面,並且認爲它看起來像比它值得的更努力的方式,哈哈。我也不太確定這是否會返回部分結果,你知道嗎? – Apollys

+0

@Abollys博客的措辭使我覺得它不會返回任何東西。他們並沒有說明這個方面的工作原理。 –

+0

@Apollys文章中提到的「限制查詢時間」是值得的。 –