Decoupling to Improve Performance
Learn how to decouple processing to give the impression of improved performance.
oracle miscconfigurationintermediate
by OracleDba
13 views
Learn how to decouple processing to give the impression of improved performance.
12345678910111213141516171819202122232425262728293031
CONN / AS SYSDBA
-- DROP USER testuser1 CASCADE;
-- Create test user.
CREATE USER testuser1 IDENTIFIED BY testuser1
QUOTA UNLIMITED ON users;
GRANT CREATE SESSION, CREATE PROCEDURE TO testuser1;
GRANT EXECUTE ON DBMS_LOCK TO testuser1;
CONN testuser1/testuser1
CREATE OR REPLACE PROCEDURE slow_request (p_username IN VARCHAR2,
p_request_info IN VARCHAR2) AS
BEGIN
-- Pretend to do some work for 10 seconds.
DBMS_LOCK.sleep(10);
END slow_request;
/
SHOW ERRORS
SQL> SET TIMING ON
SQL> EXEC slow_request('Tim', 'Pay me lots of money!');
PL/SQL procedure successfully completed.
Elapsed: 00:00:10.05
SQL> SET TIMING OFF
SQL>1234567891011121314151617181920212223242526272829
-- (adjust usernames as required).
CONNECT / AS SYSDBA
GRANT CREATE TYPE TO testuser1;
GRANT AQ_ADMINISTRATOR_ROLE, AQ_USER_ROLE TO testuser1;
GRANT EXECUTE ON DBMS_AQ TO testuser1;
CONNECT testuser1/testuser1
-- Create payload database type.
CREATE OR REPLACE TYPE slow_request_type AS OBJECT (
username VARCHAR2(30),
request_info VARCHAR2(2000)
);
/
-- Create and start queue.
BEGIN
DBMS_AQADM.create_queue_table (
queue_table => USER || '.slow_request_queue_tab',
queue_payload_type => USER || '.slow_request_type');
DBMS_AQADM.create_queue (queue_name => USER || '.slow_request_queue',
queue_table => USER || '.slow_request_queue_tab');
DBMS_AQADM.start_queue (queue_name => USER || '.slow_request_queue',
enqueue => TRUE);
END;
/12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
CREATE OR REPLACE PACKAGE slow_request_api AS
PROCEDURE enqueue (p_username IN VARCHAR2,
p_request_info IN VARCHAR2);
PROCEDURE dequeue (p_username OUT VARCHAR2,
p_request_info OUT VARCHAR2);
PROCEDURE process_requests_job;
END slow_request_api;
/
SHOW ERRORS
CREATE OR REPLACE PACKAGE BODY slow_request_api AS
g_schema VARCHAR2(30) := USER;
g_process_job_loop NUMBER := 100;
-- -----------------------------------------------------------------
PROCEDURE enqueue (p_username IN VARCHAR2,
p_request_info IN VARCHAR2) AS
-- -----------------------------------------------------------------
l_enqueue_options DBMS_AQ.enqueue_options_t;
l_message_properties DBMS_AQ.message_properties_t;
l_message_handle RAW(16);
l_slow_request_msg slow_request_type;
BEGIN
l_slow_request_msg := slow_request_type(p_username, p_request_info);
DBMS_AQ.enqueue(queue_name => g_schema || '.slow_request_queue',
enqueue_options => l_enqueue_options,
message_properties => l_message_properties,
payload => l_slow_request_msg,
msgid => l_message_handle);
END enqueue;
-- -----------------------------------------------------------------
-- -----------------------------------------------------------------
PROCEDURE dequeue (p_username OUT VARCHAR2,
p_request_info OUT VARCHAR2) AS
-- -----------------------------------------------------------------
l_dequeue_options DBMS_AQ.dequeue_options_t;
l_message_properties DBMS_AQ.message_properties_t;
l_message_handle RAW(16);
l_slow_request_msg slow_request_type;
BEGIN
-- Don't wait on the queue for a message to arrive.
l_dequeue_options.wait := DBMS_AQ.no_wait;
DBMS_AQ.dequeue(queue_name => g_schema || '.slow_request_queue',
dequeue_options => l_dequeue_options,
message_properties => l_message_properties,
payload => l_slow_request_msg,
msgid => l_message_handle);
p_username := l_slow_request_msg.username;
p_request_info := l_slow_request_msg.request_info;
END dequeue;
-- -----------------------------------------------------------------
-- -----------------------------------------------------------------
PROCEDURE process_requests_job AS
-- -----------------------------------------------------------------
l_username VARCHAR2(30);
l_request_info VARCHAR2(2000);
ex_timeout EXCEPTION;
PRAGMA EXCEPTION_INIT(ex_timeout, -25228);
BEGIN
-- Dequeuing one message at a time. Could improve performance using
-- DBMS_AQ.DEQUEUE_ARRAY for array processing.
FOR i IN 1 .. g_process_job_loop LOOP
dequeue(p_username => l_username,
p_request_info => l_request_info);
slow_request(p_username => l_username,
p_request_info => l_request_info);
END LOOP;
EXCEPTION
WHEN ex_timeout THEN
-- Queue is empty.
NULL;
END process_requests_job;
-- -----------------------------------------------------------------
END slow_request_api;
/
SHOW ERRORS123456789101112131415161718192021222324252627282930313233343536373839404142434445
SET SERVEROUTPUT ON
DECLARE
l_start NUMBER;
l_loops NUMBER := 5;
BEGIN
-- Time the original method.
l_start := DBMS_UTILITY.get_time;
FOR i IN 1 .. l_loops LOOP
slow_request(p_username => 'Tim',
p_request_info => 'Pay me lots of money!');
END LOOP;
DBMS_OUTPUT.put_line('Original Method : ' ||
(DBMS_UTILITY.get_time - l_start) || ' hsecs');
-- Time the decoupled method.
l_start := DBMS_UTILITY.get_time;
FOR i IN 1 .. l_loops LOOP
slow_request_api.enqueue(
p_username => 'Tim',
p_request_info => 'This is dummy data');
END LOOP;
DBMS_OUTPUT.put_line('Decoupled Method: ' ||
(DBMS_UTILITY.get_time - l_start) || ' hsecs');
-- Time the background processing.
l_start := DBMS_UTILITY.get_time;
slow_request_api.process_requests_job;
DBMS_OUTPUT.put_line('Background Proc : ' ||
(DBMS_UTILITY.get_time - l_start) || ' hsecs');
END;
/
Original Method : 5006 hsecs
Decoupled Method: 1 hsecs
Background Proc : 5010 hsecs
PL/SQL procedure successfully completed.
Elapsed: 00:01:40.21
SQL>1234567891011121314
DROP PACKAGE slow_request_api;
DROP PROCEDURE slow_request;
BEGIN
DBMS_AQADM.stop_queue (queue_name => USER || '.slow_request_queue',
enqueue => TRUE);
DBMS_AQADM.drop_queue (queue_name => USER || '.slow_request_queue');
DBMS_AQADM.drop_queue_table (queue_table => USER || '.slow_request_queue_tab');
END;
/
DROP TYPE slow_request_type;Please to add comments
No comments yet. Be the first to comment!