Understanding Advanced Queuing

Download Report

Transcript Understanding Advanced Queuing

Advanced Queuing
Internals
Julian Dyke
Independent Consultant
Web Version - November 2008
1
© 2008 Julian Dyke
juliandyke.com
Agenda







2
© 2008 Julian Dyke
Introduction
Single Consumer Queues
Multiple Consumer Queues
 Recipients
 Subscribers
Exception Queues
Array Payloads
Buffered Messages
 Spilled Messages
Performance
juliandyke.com
Introduction
Advanced Queuing
3

Advanced Queuing
 Introduced in Oracle 8.0
 Extended and enhanced in most subsequent versions
 Supports Oracle Streams in Oracle 9.2 and above
 Supports buffered messages in Oracle 10.2 and above

Allows messages to be enqueued and dequeued from queues that are
managed by the database

Each queue is associated with a queue table
 Properties of queue table specify behaviour of associated queues

Each queue has a payload which can be:
 RAW - only messages of type RAW can be enqueued
 Object type- only messages of the specified type can be enqueued
 ANYDATA - messages with any object type can be enqueued
© 2008 Julian Dyke
juliandyke.com
Introduction
Advanced Queuing

By default messages are dequeued in the order they are enqueued
 Default behaviour can be overridden in several ways

Messages can be persistent or buffered
 Persistent messages
 Stored in queue table
 Survive an instance restart


4
Buffered messages
 Stored in SGA
 Can be spilled to queue table
 Lost during instance restart
Messages can be immediate or on-commit
 Immediate messages are committed immediately when they are
enqueued/dequeued
 On-commit messages are committed with the enqueuing transaction
 Buffered messages can only be immediate.
© 2008 Julian Dyke
juliandyke.com
Introduction
Advanced Queuing
5

Queue tables can be created for single or multiple consumers
 Messages in single consumer queue tables can only be dequeued once
 Messages in multiple consumer queue tables can be dequeued multiple
times by multiple consumers

Multiple consumer queue tables can be associated with
 Multiple recipients
 Multiple subcribers

Subscribers can:
 Specify rules to control which messages they dequene
 Specify transformations to be performed against dequeued data
© 2008 Julian Dyke
juliandyke.com
Advanced Queuing
Introduction
6

Sessions can listen for messages on multiple queues
 Session is notified when a message arrives on any of the target queues

Queue messages can be propagated from one queue to another
 In the same database
 In different databases
 Propagation can be immediate or at specified intervals

Transformation converts payload from one object type to another
 Queue data can be transformed when messages are:
 Enqueued
 Propagated
 Dequeued
 Messages must be transformed using DBMS_TRANSFORM API
© 2008 Julian Dyke
juliandyke.com
Introduction
Payloads

Queue payloads can be
 RAW
 Abstract data types
 ANYDATA

Abstract data types
 Maximum number of attributes is limited to 900
 For example:
CREATE TYPE type1 AS OBJECT
(
c1 NUMBER,
c2 NUMBER,
c3 NUMBER
);
/
7
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Queue Tables





Every queue must be associated with a queue table
Queue table defines properties of queue
Reported in DBA_QUEUE_TABLES
Managed using DBMS_AQADM
For example:
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','RAW');
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','TYPE1');


8
By default single consumer queues will be created
Each queue table can contain multiple queues
 Queues inherit properties of queue table
 Each queue table block contains blocks for one queue
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Queue Table Columns (RAW Payload)
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','RAW');

Queue table QT1 contains the following columns:
Col# Intcol# Column Name
9
Data Type
Col# Intcol# Column Name
Data Type
1
1 Q_NAME
VARCHAR2(30)
16
16 DEQ_TIME
TIMESTAMP(6)
2
2 MSG_ID
RAW(16)
17
17 DEQ_UID
VARCHAR2(30)
3
3 CORRID
VARCHAR2(128)
18
18 DEQ_TID
VARCHAR2(30)
4
4 PRIORITY
NUMBER
19
19 RETRY_COUNT
NUMBER
5
5 STATE
NUMBER
20
20 EXCEPTION_QSCHEMA VARCHAR2(30)
6
6 DELAY
TIMESTAMP(6)
21
21 EXCEPTION_QUEUE
VARCHAR2(30)
7
7 EXPIRATION
NUMBER
22
22 STEP_NO
NUMBER
8
8 TIME_MANAGER_INFO TIMESTAMP(6)
23
23 RECIPIENT_KEY
NUMBER
9
9 LOCAL_ORDER_NO
NUMBER
24
24 DEQUEUE_MSG_ID
RAW(16)
10
10 CHAIN_NO
NUMBER
25
25 SENDER_NAME
VARCHAR2(30)
11
11 CSCN
NUMBER
26
26 SENDER_ADDRESS
VARCHAR2(1024)
12
12 DSCN
NUMBER
27
27 SENDER_PROTOCOL
NUMBER
13
13 ENQ_TIME
TIMESTAMP(6)
28
28 USER_DATA
BLOB
14
14 ENQ_UID
VARCHAR2(30)
29
29 USER_PROP
SYS.ANYDATA
15
15 ENQ_TID
VARCHAR2(30)
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Queue Table Columns (Object Payload)
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','TYPE1');

Queue table QT1 contains the following columns:
Col# Intcol# Column Name
10
Data Type
Col# Intcol# Column Name
Data Type
1
1 Q_NAME
VARCHAR2(30)
17
17 DEQ_UID
VARCHAR2(30)
2
2 MSG_ID
RAW(16)
18
18 DEQ_TID
VARCHAR2(30)
3
3 CORRID
VARCHAR2(128)
19
19 RETRY_COUNT
NUMBER
4
4 PRIORITY
NUMBER
20
20 EXCEPTION_QSCHEMA VARCHAR2(30)
5
5 STATE
NUMBER
21
21 EXCEPTION_QUEUE
VARCHAR2(30)
6
6 DELAY
TIMESTAMP(6)
22
22 STEP_NO
NUMBER
7
7 EXPIRATION
NUMBER
23
23 RECIPIENT_KEY
NUMBER
8
8 TIME_MANAGER_INFO TIMESTAMP(6)
24
24 DEQUEUE_MSG_ID
RAW(16)
9
9 LOCAL_ORDER_NO
NUMBER
25
25 SENDER_NAME
VARCHAR2(30)
10
10 CHAIN_NO
NUMBER
26
26 SENDER_ADDRESS
VARCHAR2(1024)
11
11 CSCN
NUMBER
27
27 SENDER_PROTOCOL
NUMBER
12
12 DSCN
NUMBER
28
28 USER_DATA
TYPE1
13
13 ENQ_TIME
TIMESTAMP(6)
28
29 SYS_NC00029$
NUMBER
14
14 ENQ_UID
VARCHAR2(30)
28
30 SYS_NC00030$
NUMBER
15
15 ENQ_TID
VARCHAR2(30)
28
31 SYS_NC00031$
NUMBER
16
16 DEQ_TIME
TIMESTAMP(6)
29
32 USER_PROP
SYS.ANYDATA
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Database Objects (RAW payload)
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','RAW');


11
The following objects will be created (object IDs and constraint IDs will vary):
Object ID
Object Name
Object Type
70581
QT1
TABLE
70582
SYS_LOB0000070581C00028$$
LOB
70583
SYS_IL0000070581C00028$$
LOB INDEX
70584
SYS_LOB0000070581C00029$$
LOB
70585
SYS_IL0000070581C00029$$
LOB INDEX
70586
SYS_C009433
INDEX
70587
AQ$_QT1_T
INDEX
70588
AQ$_QT1_I
INDEX
70589
QT70581_BUFFER
VIEW
70590
AQ$QT1
VIEW
70591
AQ$_QT1_F
VIEW
70592
AQ$_QT1_E
QUEUE
LOB columns are used for USER_DATA and USER_PROP columns
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Database Objects (Object Payload)
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','TYPE1');


12
The following objects will be created (object IDs and constraint IDs will vary):
Object ID
Object Name
Object Type
70581
QT1
TABLE
70582
SYS_LOB0000070581C00032$$
LOB
70583
SYS_IL0000070581C00032$$
LOB INDEX
70584
SYS_C009433
INDEX
70585
AQ$_QT1_T
INDEX
70586
AQ$_QT1_I
INDEX
70587
QT70581_BUFFER
VIEW
70589
AQ$QT1
VIEW
70590
AQ$_QT1_F
VIEW
70591
AQ$_QT1_E
QUEUE
LOB column is used for USER_PROP column
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Index Columns
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT1','TYPE1');

The following indexes will be created by default (constraint IDs will vary):
Index Name
Column #
Column Name
SYS_C009436
1
MSGID
AQ$_QT1_I
1
Q_NAME
2
STATE
3
ENQ_TIME
4
STEP_NO
5
CHAIN_NO
6
LOCAL_ORDER_NO
1
TIME_MANAGER_INFO
AQ$_QT1_T
13
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Sort Lists




The columns indexed by AQ$_QTI are determined by the SORT_LIST
parameter.
Possible values are
 enq_time (default)
DBMS_AQADM.CREATE_QUEUE_TABLE
 priority
('QT1','TYPE1',SORT_LIST=>"priority,enq_time");
 priority,enq_time
 enq_time,priority
Must be defined when queue table is created
Cannot be subsequently altered
Column #
enq_time
priority
priority,enq_time
enq_time,priority
1
Q_NAME
Q_NAME
Q_NAME
Q_NAME
2
STATE
STATE
STATE
STATE
3
ENQ_TIME
PRIORITY
PRIORITY
ENQ_TIME
4
STEP_NO
CHAIN_NO
ENQ_TIME
STEP_NO
5
CHAIN_NO
LOCAL_ORDER_NO
STEP_NO
PRIORITY
6
LOCAL_ORDER_NO
CHAIN_NO
CHAIN_NO
LOCAL_ORDER_NO
LOCAL_ORDER_NO
7
14
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Views
15

Two views are created for each queue table

For example for QT1 (object ID =70581):

QT<object_id>_BUFFER
 e.g. QT70581_BUFFER
 based on X$BUFFER2

AQ$_<queue_table_name>_F
 e,g. AQ$_QT1_F
 based on QT1 and ALL_DEQUEUE_QUEUES
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Views

Two views are created for each queue table

For example for QT1 (object ID =70581)
 QT70581_BUFFER
 AQ$_QT1_F

QT70581_BUFFER is defined as follows:
SELECT
"ADDR", "INDX", "INST_ID", "OBJNO", "QUEUE_ID", "MSGID", "CORRID",
"SEQUENCE_NUM", "MSG_NUM", "STATE", "PRIORITY", "EXPIRATION",
"ENQ_TIME", "ENQ_UID", "ENQ_USER_NAME", "RETRY_COUNT",
"SENDER_NAME", "SENDER_ADDRESS", "SENDER_PROTOCOL",
"DEQUEUE_MSGID", "SRCSEQUENCE_NUM", "SUBSCRIBER_ID",
"EXCEPTIONQ_SCHEMA", "EXCEPTIONQ_NAME"
FROM X$BUFFER2
WHERE objno = 70581;
16
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Views

AQ$_QT1_F is defined as follows:
SELECT
qt.q_name Q_NAME, qt.rowid ROW_ID, qt.msgid MSGID, qt.corrid CORRID,
qt.priority PRIORITY, qt.state STATE, qt.delay DELAY, qt.expiration EXPIRATION,
qt.enq_time ENQ_TIME, qt.enq_uid ENQ_UID, qt.enq_tid ENQ_TID,
qt.deq_time DEQ_TIME, qt.deq_uid DEQ_UID, qt.deq_tid DEQ_TID,
qt.retry_count RETRY_COUNT, qt.exception_qschema EXCEPTION_QSCHEMA,
qt.exception_queue EXCEPTION_QUEUE, qt.cscn CSCN, qt.dscn DSCN,
qt.chain_no CHAIN_NO, qt.local_order_no LOCAL_ORDER_NO,
qt.time_manager_info TIME_MANAGER_INFO, qt.step_no STEP_NO,
qt.user_data USER_DATA , qt.sender_name SENDER_NAME,
qt.sender_address SENDER_ADDRESS, qt.sender_protocol SENDER_PROTOCOL,
qt.dequeue_msgid DEQUEUE_MSGID, 'PERSISTENT' DELIVERY_MODE,
0 SEQUENCE_NUM, 0 MSG_NUM, qo.qid QUEUE_ID,
qt.user_prop USER_PROP
FROM
"QT1" qt,
ALL_DEQUEUE_QUEUES qo
WHERE qt.q_name = qo.name
AND qo.owner = 'US01'
WITH READ ONLY;
17
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Queues
Every queue must be associated with a queue table
 Queue table must exist before queue can be created

DBMS_AQADM.CREATE_QUEUE
(queue_name => 'Q1',queue_table => 'QT1');

18
This statement might create the following object:
Object ID
Object Name
Object Type
70793
Q1
QUEUE

Every queue has a type which can be:
 NORMAL (default)
 EXCEPTION
 NON PERSISTENT

Non persistent queues are deprecated in Oracle 10.2
 Use buffered messages instead
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Enqueue

The following code enqueues a message of TYPE1 on a single consumer
queue:
DECLARE
message TYPE1;
msgprop dbms_aq.message_properties_t;
enqopt dbms_aq.enqueue_options_t;
enq_msgid RAW(16);
BEGIN
message := new TYPE1 (10001,20001,30001);
msgprop.expiration :=DBMS_AQ.NEVER
dbms_aq.enqueue
(
queue_name => 'Q1',
enqueue_options => enqopt,
message_properties => msgprop,
payload => message,
msgid => enq_msgid
);
END;
19
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Enqueue

The enqueue processes executes the following recursive statement:
insert into "US01"."QT1" (q_name, msgid, corrid, priority, state, delay, expiration,
time_manager_info, local_order_no, chain_no, enq_time, step_no, enq_uid, enq_tid,
retry_count, exception_qschema, exception_queue, recipient_key, dequeue_msgid,
user_data, sender_name, sender_address, sender_protocol, user_prop, cscn, dscn)
values (:1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, 0, :15,:16, :17, :18, :19, :20, :21,
:22, :23, :24, :25)

In Oracle 11.1 this statement uses the LOAD TABLE CONVENTIONAL
operation
STAT #3 id=1 cnt=0 pid=0 pos=1 obj=0 op='LOAD TABLE CONVENTIONAL (cr=1 pr=5 pw=5
time=0 us)')

20
For this statement the following objects are modified
© 2008 Julian Dyke
Object ID
Object Name
Object Type
70581
QT1
TABLE
70586
SYS_C009433
INDEX
70588
AQ$_QT1_1
INDEX
juliandyke.com
Single Consumer Queues
Dequeue

The following code dequeues a message of TYPE1 from a single consumer
queue:
DECLARE
message TYPE1;
msgprop dbms_aq.message_properties_t;
deqopt dbms_aq.dequeue_options_t;
deq_msgid RAW(16);
BEGIN
dbms_aq.dequeue
(
queue_name => 'Q1',
dequeue_options => deqopt,
message_properties => msgprop,
payload => message,
msgid => deq_msgid
);
END;
21
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Dequeue

The dequeue processes executes the following recursive statement:
select /*+ FIRST_ROWS(1) */ tab.rowid, tab.msgid, tab.corrid, tab.priority, tab.delay,
tab.expiration, tab.retry_count, tab.exception_qschema, tab.exception_queue, tab.chain_no,
tab.local_order_no, tab.enq_time, tab.time_manager_info, tab.state, tab.enq_tid, tab.step_no,
tab.sender_name, tab.sender_address, tab.sender_protocol, tab.dequeue_msgid,
tab.user_prop, tab.user_data
from "US01"."QT1" tab
where q_name = :1 and (state = :2 )
order by q_name, state, enq_time, step_no, chain_no, local_order_no
for update skip locked




22
The statement selects all rows in the queue specified by :1 with a state of :2
The FIRST_ROWS(1) hint is used to optimize the plan
The statement locks any rows to be deleted
 This will generate undo/redo
The statement uses the FOR UPDATE SKIP LOCKED clause to skip any rows
still locked by ongoing transactions
© 2008 Julian Dyke
juliandyke.com
Single Consumer Queues
Dequeue

Execution plan for SELECT FOR UPDATE statement is:
STAT #3 id=1 cnt=1 pid=0 pos=1 obj=0 op='FOR UPDATE (cr=7 pr=2 pw=2 time=0 us)'
STAT #3 id=2 cnt=1 pid=1 pos=1 obj=0 op='SORT ORDER BY (cr=7 pr=0 pw=0 time=0 us
cost=4 size=2759 card=1)'
STAT #3 id=3 cnt=1 pid=2 pos=1 obj=70581 op='TABLE ACCESS FULL QT1 (cr=7 pr=0 pw=0
time=0 us cost=3 size=2759 card=1)'

As queue grows, object statistics must be gathered to
 ensure AQ$_QT1_I index is used
 prevent full table scans on QT1

Rows identified by SELECT FOR UPDATE are deleted using:
delete /*+ CACHE_CB("QT9") */ from "US01"."QT1" where rowid = :1

Execution plan for DELETE statement is:
STAT #7 id=1 cnt=1 pid=0 pos=1 obj=0 op='DELETE QT1 (cr=1 pr=2 pw=2 time=0 us)'
STAT #7 id=2 cnt=1 pid=1 pos=1 obj=70581 op='TABLE ACCESS BY USER ROWID QT1
(cr=1 pr=0)'
23
© 2008 Julian Dyke
juliandyke.com
Queues
Exception Queues

A default exception queue is created for each queue table
 Exception messages will be moved to default queue unless a userdefined exception queue has been specified when the message is
enqueued

For example to create a user-defined exception queue
DBMS_AQADM.CREATE_QUEUE
(queue_name => 'Q1',queue_table => 'QT1');
DBMS_AQADM.CREATE_QUEUE
(queue_name => 'Q1E',queue_table => 'QT1'
queue_type => DBMS_AQADM.EXCEPTION_QUEUE);

Object ID
Object Name
Object Type
Queue Type
70793
Q1
QUEUE
NORMAL
70794
Q1E
QUEUE
EXCEPTION
To check number of rows in each queue:
SELECT q_name, COUNT(*)
FROM qt1
GROUP BY q_name;
24
© 2008 Julian Dyke
juliandyke.com
Queues
Exception Queues

Exceptions will be written to user-defined exception queue if it is specified
during enqueue operation
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_enqopt dbms_aq.enqueue_options_t;
l_enq_msgid RAW(16);
BEGIN
l_payload := new TYPE1 (10001,20001,30001);
l_msgprop.expiration := 60;
l_msgprop.exception_queue := 'Q1E';
dbms_aq.enqueue
(
queue_name => 'Q1',
enqueue_options => l_enqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_enq_msgid
);
END;

25
Message will expire after 60 seconds
 Expired message will be move to exception queue Q1E by queue monitor
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Introduction

There are two ways to use multiple consumer queues
 Multiple Recipients
 Multiple Subscribers

The same queue definitions are used for both examples:
BEGIN
dbms_aqadm.create_queue_table
('QT3','TYPE1',multiple_consumers=>TRUE)
dbms_aqadm.create_queue ('Q3','QT3');
dbms_aqadm.start_queue ('Q3');
END;
/
26
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Database Objects
DBMS_AQADM.CREATE_QUEUE_TABLE
('QT1','TYPE1',MULTIPLE_CONSUMERS=>TRUE);

27
The following objects will be created (object IDs and constraint IDs will vary):
Object ID
Object Name
Object Type
Object ID
Object Name
Object Type
70756
QT1
TABLE
70767
AQ$_QT1_H
TABLE
70757
SYS_LOB0000070581C00032$$
LOB
70768
SYS_IOT_TOP_70767
INDEX
70758
SYS_IL0000070581C00032$$
LOB INDEX
70769
AQ$_QT1_G
TABLE
70759
SYS_C009457
INDEX
70770
SYS_IOT_OVER_70769
TABLE
70760
AQ$_QT1_S
TABLE
70771
SYS_IOT_TOP_70769
INDEX
70761
SYS_C009460
INDEX
70772
AQ$_QT1_I
TABLE
70762
AQ$_QT1_N
SEQUENCE
70773
SYS_IOT_TOP_70772
INDEX
70763
AQ$QT1_S
VIEW
70774
QT70756_BUFFER
VIEW
70764
AQ$_QT1_V
EVAL CTXT
70775
AQ$QT1
VIEW
70765
AQ$_QT1_T
TABLE
70776
AQ$_QT1_F
VIEW
70766
SYS_IOT_TOP_70765
INDEX
70777
AQ$_QT1_E
QUEUE
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Tables
28

AQ$_<queue_table_name>_T e.g AQ$_QT3_T
 IOT used queue monitor to manage timed operations
 Single consumer queues use TIME_MANAGER_INFO column only

AQ$_<queue_table_name>_I
 IOT that maintains state for dequeue operations
 One row per message per recipient/subscriber

AQ$_<queue_table_name>_S
 Heap table containing information about subscribers

AQ$_<queue_table_name>_H
 IOT used to store dequeue history
 One row per message per recipient/subscriber

AQ$_<queue_table_name>_G
 IOT correlating messages to subscriber signatures
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Tables

29
AQ$_<queue_table_name>_T
 IOT used queue monitor to manage timed operations
 e.g. AQ$_QT3_T
Column Name
Data Type
NEXT_DATE
TIMESTAMP
TXN_ID
VARCHAR2(30)
MSGID
RAW(16)
ACTION
NUMBER

First 3 columns form primary key

Values for the ACTION column include:
 0 - delay
 1 - expiration
 2 - delay

Single consumer queues use TIME_MANAGER_INFO column only
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Tables



30
AQ$_<queue_table_name>_I
 IOT that maintains state for dequeue operations
Column Name
Data Type
SUBSCRIBER
NUMBER
NAME
VARCHAR2(30)
QUEUE#
NUMBER
MSG_ENQ_TIME
TIMESTAMP
MSG_STEP_NO
NUMBER
MSG_CHAIN_NO
NUMBER
MSG_LOCAL_ORDER_NO
NUMBER
MSG_ID
RAW(16)
HINT
ROWID
SPARE
RAW(16)
First eight columns form primary key
HINT and SPARE columns are stored in IOT overflow segment
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Tables

31
AQ$_<queue_table_name>_S
 Heap table containing information about subscribers
© 2008 Julian Dyke
Column Name
Data Type
SUBSCRIBER_ID
NUMBER
QUEUE_NAME
VARCHAR2(30)
NAME
VARCHAR2(30)
ADDRESS
VARCHAR2(1024)
PROTOCOL
NUMBER
SUBSCRIBER_TYPE
NUMBER
RULE_NAME
VARCHAR2(30)
TRANS_NAME
VARCHAR2(65)
RULESET_NAME
VARCHAR2(65)
NEGATIVE_RULESET_NAME
VARCHAR2(65)
CREATION_TIME
TIMESTAMP(6)
MODIFICATION_TIME
TIMESTAMP(6)
DELETION_TIME
TIMESTAMP(6)
SCN_AT_REMOVE
NUMBER
juliandyke.com
Multiple Consumer Queues
Tables



32
AQ$_<queue_table_name>_H
 IOT used to store dequeue history
Column Name
Data Type
MSGID
RAW(16)
SUBSCRIBER#
NUMBER
NAME
VARCHAR2(30)
ADDRESS#
NUMBER
DEQUEUE_TIME
TIMESTAMP
TRANSACTION_ID
VARCHAR2(30)
DEQUEUE_USER
VARCHAR2(30)
PROPAGATED_MSGID
RAW(16)
RETRY_COUNT
NUMBER
HINT
ROWID
SPARE
RAW(16)
First four columns form primary key
No IOT overflow segment
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Tables


33
AQ$_<queue_table_name>_G
 IOT correlating messages to subscriber signatures
Column Name
Data Type
NAME
VARCHAR2(30)
ADDRESS#
NUMBER
SIGN
SYS.AQ$_SIG_PROP
DBS_SIGN
SYS.AQ$_SIG_PROP
All columns form primary key
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Indexes



34
By default six indexes are created for each queue table. For example:
Index Name
Index Type
# Columns
Table Name
SYS_C009457
NORMAL
1
QT3
SYS_C009460
NORMAL
1
AQ$_QT3_S
SYS_IOT_TOP_70765
IOT
3
AQ$_QT3_T
SYS_IOT_TOP_70767
IOT
4
AQ$_QT3_H
SYS_IOT_TOP_70769
IOT
4
AQ$_QT3_G
SYS_IOT_TOP_70772
IOT
8
AQ$_QT3_I
Index columns for NORMAL indexes are:
Index Name
Column #
Column Name
SYS_C009457
1
MSGID
SYS_C009460
1
SUBSCRIBER_ID
Index columns for IOT indexes are shown on previous slides
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Views


35
Three views are created for each queue table
For example for QT3 (object ID = 70756)
 QT70756_BUFFER
 AQ$_QT3_F
 AQ$QT3

<queue_object_Id>_BUFFER e.g QT70756_BUFFER
 Similar for single and multiple consumers

AQ$_<queue_table_name>_F e.g AQ$_QT3_F
 Similar for single and multiple consumers

AQ$<queue_table_name> views e.g. AQ$QT3
 Based on:
 Queue table (QT3)
 History IOT (AQ$_QT3_H)
 Subscriber table (AQ$_QT3_S)
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Views

AQ$<queue_table_name> views (AQ$QT3) are based on:
 Queue table (QT3)
 History IOT (AQ$_QT3_H)
 Subscriber table (AQ$_QT3_S)

Abbreviated definition is as follows:
SELECT
<column_list>
FROM
"QT8" qt,
"AQ$_QT8_H" h,
"AQ$_QT8_S" s
WHERE qt.msgid = h.msgid
AND ((h.subscriber# != 0 AND h.subscriber# = s.subscriber_id)
OR (h.subscriber# = 0 AND h.address# = s.subscriber_id))
AND (qt.state != 7 OR qt.state != 9)
WITH READ ONLY;

36
Best view to understand current state of queue for all subscribers
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Views

AQ$QT3 contains the following columns
Column Name
Data Type
Column Name
Data Type
QUEUE
VARCHAR2(30)
RETRY_COUNT
NUMBER
MSG_ID
RAW(16)
EXCEPTION_QUEUE_OWNER
VARCHAR2(30)
CORR_ID
VARCHAR2(128)
EXCEPTION_QUEUE
VARCHAR2(30)
MSG_PRIORITY
NUMBER
USER_DATA
TYPE1
MSG_STATE
VARCHAR2(16)
PROPAGATED_MSGID
RAW(16)
DELAY
DATE
SENDER_NAME
VARCHAR2(30)
DELAY_TIMESTAMP
TIMESTAMP(6)
SENDER_ADDRESS
VARCHAR2(1024)
EXPIRATION
NUMBER
SENDER_PROTOCOL
NUMBER
ENQ_TIME
DATE
ORIGINAL_MSGID
RAW(16)
ENQ_TIMESTAMP
TIMESTAMP(6)
ORIGINAL_QUEUE_NAME
VARCHAR2(30)
ENQ_USER_ID
VARCHAR2(30)
ORIGINAL_QUEUE_OWNER
VARCHAR2(30)
ENQ_TXN_ID
VARCHAR2(30)
EXPIRATION_REASON
VARCHAR2(31)
DEQ_TIME
DATE
CONSUMER_NAME
VARCHAR2(30)
DEQ_TIMESTAMP
TIMESTAMP(6)
ADDRESS
VARCHAR2(1024)
DEQ_USER_ID
VARCHAR2(30)
PROTOCOL
NUMBER
DEQ_TXN_ID
VARCHAR2(30)
37
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Recipients

The following code enqueues a message for three named recipients
DECLARE
l_payload type1;
l_msgprop dbms_aq.message_properties_t;
l_enqopt dbms_aq.enqueue_options_t;
l_enq_msgid RAW(16);
l_recipient_list dbms_aq.aq$_recipient_list_t;
BEGIN
l_recipient_list(1) := sys.aq$_agent ('CONSUMER1',NULL,NULL);
l_recipient_list(2) := sys.aq$_agent ('CONSUMER2',NULL,NULL);
l_recipient_list(3) := sys.aq$_agent ('CONSUMER3',NULL,NULL);
l_msgprop.recipient_list := l_recipient_list;
l_msgprop.expiration := DBMS_AQ.NEVER;
l_payload := new TYPE1 (10001,20001,30001);
dbms_aq.enqueue
(
queue_name => 'Q3',
enqueue_options => l_enqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_enq_msgid
);
END;
38
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Recipients
39

A recipient list is constructed using AQ$_AGENT objects
 In the example all recipients are in the local database

The enqueue operation performs the following actions:
 Inserts one row in the queue table (QT3)
 Inserts three rows in the queue status table (AQ$_QT3_I)
 Inserts three rows in the queue history table (AQ$_QT3_H)
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Recipients

The following code dequeues a message for one of the named recipients
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_deqopt dbms_aq.dequeue_options_t;
l_deq_msgid RAW(16);
BEGIN
l_deqopt.consumer_name := 'CONSUMER2';
dbms_aq.dequeue
(
queue_name => 'Q3',
dequeue_options => l_deqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_deq_msgid
);
END;

40
Notes
 A consumer name MUST be specified
 The message must have been enqueued specifically for that consumer
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Recipients
41

The dequeue operation performs the following actions
 Deletes one row from the queue status IOT (AQ$_QT3_I)
 Updates the following columns in one row of the queue history IOT
(AQ$_QT3_H)
 DEQUEUE_TIME
 TRANSACTION_ID
 DEQUEUE_USER
 Inserts one row into the queue timer table (AQ$_QT3_T)

The queue monitor (QMNC) process asynchronously checks the timer table
(AQ$_QT3_T) for actions
 If any actions are found these are sent to the queue monitor slaves (Q001,
Q002 etc)

When last recipient has dequeued message, queue monitor slaves perform
the following actions
 Delete all rows for message in queue history table (AQ$_QT3_H)
 Delete row in queue table (QT3) for message
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Subscribers


Subscribers must exist for the queue before messages can be enqueued
The following code creates two subscribers for queue Q3
DECLARE
l_subscriber sys.aq$_agent;
BEGIN
l_subscriber := sys.aq$_agent ('SUBSCRIBER1',NULL,NULL);
DBMS_AQADM.ADD_SUBSCRIBER
(
queue_name => 'Q3',
subscriber => l_subscriber
);
l_subscriber := sys.aq$_agent ('SUBSCRIBER2',NULL,NULL);
DBMS_AQADM.ADD_SUBSCRIBER
(
queue_name => 'Q3',
subscriber => l_subscriber
);
END;

42
Creating a subscriber inserts one row in the AQ$_QT3_S table
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Subscribers

The following code enqueues ten messages on Q3
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_enqopt dbms_aq.enqueue_options_t;
l_enq_msgid RAW(16);
BEGIN
FOR f IN 1..10
LOOP
l_payload := new TYPE1 (10000 + f,20000 + f,30000 + f);
l_msgprop.expiration := DBMS_AQ.NEVER;
dbms_aq.enqueue
(
queue_name => 'Q3',
enqueue_options => l_enqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_enq_msgid
);
END LOOP;
END;
43
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Subscribers

The following code dequeues a message from Q3 for SUBSCRIBER1
SET SERVEROUTPUT ON
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_deqopt dbms_aq.dequeue_options_t;
l_deq_msgid RAW(16);
BEGIN
l_deqopt.consumer_name := 'SUBSCRIBER1';
dbms_aq.dequeue
(
queue_name => 'Q3',
dequeue_options => l_deqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_deq_msgid
);
DBMS_OUTPUT.PUT_LINE ('C1 = '||TO_CHAR (l_payload.c1));
DBMS_OUTPUT.PUT_LINE ('C2 = '||TO_CHAR (l_payload.c2));
DBMS_OUTPUT.PUT_LINE ('C3 = '||TO_CHAR (l_payload.c3));
END;
44
© 2008 Julian Dyke
juliandyke.com
Multiple Consumer Queues
Subscribers

Subscribers can subsequently be added and deleted dynamically
DECLARE
l_subscriber sys.aq$_agent;
BEGIN
l_subscriber := sys.aq$_agent ('SUBSCRIBER3',NULL,NULL);
DBMS_AQADM.ADD_SUBSCRIBER
(
queue_name => 'Q3',
subscriber => l_subscriber
);
DBMS_AQADM.REMOVE_SUBSCRIBER
(
queue_name => 'Q3',
subscriber => l_subscriber
);
END;

45
New subscribers will only be allowed to dequeue messages that have been
enqueued after the subscriber was added
© 2008 Julian Dyke
juliandyke.com
Array Payloads
Introduction


Payload of a queue can optionally be a VARRAY of object types
For example:
CREATE OR REPLACE TYPE type2 AS VARRAY (10) OF type1;
/
CREATE OR REPLACE TYPE type3 AS OBJECT (c1 type2);
/


Queue table can be created with a TYPE3 payload
 It is not possible to create a queue table with a TYPE2 payload
For example:
DBMS_AQADM.CREATE_QUEUE_TABLE ('QT3','TYPE3');
DBMS_AQADM.CREATE_QUEUE ('Q3','QT3');
DBMS_AQADM.START_QUEUE ('Q3');
46
© 2008 Julian Dyke
juliandyke.com
Array Payloads
Enqueue
DECLARE
l_payload TYPE3;
msgprop dbms_aq.message_properties_t;
enqopt dbms_aq.enqueue_options_t;
enq_msgid RAW(16);
BEGIN
l_payload := new TYPE3 (TYPE2 (
TYPE1 (10001,20001,30001),
TYPE1 (10002,20002,30002),
TYPE1 (10003,20003,30003),
TYPE1 (10004,20004,30004)
));
msgprop.expiration := DBMS_AQ.NEVER;
dbms_aq.enqueue
(
queue_name => 'Q4',
enqueue_options => enqopt,
message_properties => msgprop,
payload => l_payload,
msgid => enq_msgid
);
END;
47
© 2008 Julian Dyke
juliandyke.com
Array Payloads
Dequeue
SET SERVEROUTPUT ON
DECLARE
l_payload TYPE3;
msgprop dbms_aq.message_properties_t;
deqopt dbms_aq.dequeue_options_t;
deq_msgid RAW(16);
BEGIN
dbms_aq.dequeue
(
queue_name => 'Q4',
dequeue_options => deqopt,
message_properties => msgprop,
payload => l_payload,
msgid => deq_msgid
);
FOR i IN 1..message.c1.COUNT
LOOP
DBMS_OUTPUT.PUT ('C1 = '||TO_CHAR (l_payload.c1(i).c1)||' ');
DBMS_OUTPUT.PUT ('C2 = '||TO_CHAR (l_payload.c1(i).c2)||' ');
DBMS_OUTPUT.PUT ('C3 = '||TO_CHAR (l_payload.c1(i).c3));
DBMS_OUTPUT.NEW_LINE ();
END LOOP;
END;
48
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Introduction


49
In Oracle 10.2 and above messages can be buffered in the SGA
 Messages will not be written to database immediately
 Messages are spillled to database if:
 Number of messages exceeds threshold value
 Messages not dequeued within 10 minutes
Buffered messages
 Are much faster than persistent queues
 Do not guarantee reliability
 Cannot form part of a transaction
 Do not support (Oracle 11.1)
 Message retention / delay
 Transaction grouping
 Array enqueue / dequeue
 Message export / import
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Introduction

Buffering is specified at message level
 Queues can contain both persistent and buffered messages
 Payload can be ADT, XML, ANYDATA or RAW
 Support for LOB payloads is restricted

The following definitions are used with the examples in this section
BEGIN
dbms_aqadm.create_queue_table ('QT1','TYPE1')
dbms_aqadm.create_queue ('Q1','QT1');
dbms_aqadm.start_queue ('Q1');
END;

50
Note that all queue tables support buffered messages
 No additional attributes are specified for the queue or the queue table
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Enqueue

The following code enqueues a buffered message
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_enqopt dbms_aq.enqueue_options_t;
l_enq_msgid RAW(16);
BEGIN
l_payload := new TYPE1 (10001,20001,30001);
l_msgprop.expiration := DBMS_AQ.NEVER;
l_enqopt.visibility := DBMS_AQ.IMMEDIATE;
l_enqopt.delivery_mode := DBMS_AQ.BUFFERED;
dbms_aq.enqueue
(
queue_name => 'Q1',
enqueue_options => l_enqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_enq_msgid
);
END;
51
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Dequeue

The following code dequeues a buffered message:
SET SERVEROUTPUT ON
DECLARE
l_payload TYPE1;
l_msgprop dbms_aq.message_properties_t;
l_deqopt dbms_aq.dequeue_options_t;
l_deq_msgid RAW(16);
BEGIN
l_msgprop.expiration := DBMS_AQ.NEVER;
l_deqopt.visibility := DBMS_AQ.IMMEDIATE;
l_deqopt.delivery_mode := DBMS_AQ.BUFFERED;
dbms_aq.dequeue
(
queue_name => 'Q1',
dequeue_options => l_deqopt,
message_properties => l_msgprop,
payload => l_payload,
msgid => l_deq_msgid
);
DBMS_OUTPUT.PUT_LINE ('C1 = '||TO_CHAR (l_payload.c1));
DBMS_OUTPUT.PUT_LINE ('C2 = '||TO_CHAR (l_payload.c2));
DBMS_OUTPUT.PUT_LINE ('C3 = '||TO_CHAR (l_payload.c3));
END;
52
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Memory Usage


Memory is allocated from the Streams Pool
The following table shows the amount of streams pool memory required to
enqueue 5101 messages with the TYPE1 payload:
Before
After
Before
After
0
10,324,448
recov_kgqmsub
336
504
kwqbsinfy:mpr
480
2,448,480
kwqbsinfy:cco
332
332
image handles
84
428,512
kwqbsinfy:sta
208
312
kwqbsinfy:bms
72
387,692
spilled:kwqbl
216
288
kggmem_fl_1
44
224,444
fixed allocation callback
256
256
2,072
88,060
kgqmsub
144
216
Sender info
14,140
19,796
deqtree_kgqmctx
136
192
recov_kgqbtctx
12,288
16,384
substree_kgqmctx
120
160
kwqbcqini:spilledovermsgs
2,952
3,936
time manager index
120
160
kwqbsinfy:bqg
1,236
1,648
msgtree_kgqmctx
120
160
924
1,232
name_kgqmsub
32
48
kodpaih3
kggbt_alloc_block
recov_kggmctx
53
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Database Objects

Additional database objects are created the first time a buffered message is
enqueued on a queue table
 This will cause elapsed time of first enqueue operation to be high

For example the following objects might be created


54
Object ID
Object Name
Object Type
72638
AQ$_QT3_P
TABLE
72639
SYS_LOB0000072638C00032$$
LOB
72640
SYS_IL0000072638C00032$$
LOB INDEX
72641
SYS_C0010003
INDEX
The enqueuing session also creates a service for the queue
For example SYS$US01.Q3.TEST where
 US01 is the queue owner
 Q3 is the queue name
 TEST is the database name
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Database Objects

55
AQ$_<table_queue_name>_P contains the following columns
Column Name
Data Type
Column Name
Data Type
Q_NAME
VARCHAR2(30)
DEQ_TIME
DATE
MSGID
RAW(16)
DEQ_UID
VARCHAR2(30)
CORRID
VARCHAR2(128)
DEQ_TID
VARCHAR2(30)
PRIORITY
NUMBER
RETRY_COUNT
NUMBER
STATE
VARCHAR2(16)
EXCEPTION_QSCHEMA
VARCHAR2(30)
DELAY
DATE
EXCEPTION_QUEUE
VARCHAR2(30)
EXPIRATION
NUMBER
STEP_NO
NUMBER
TIME_MANAGER_INFO
TIMESTAMP(6)
RECIPIENT_KEY
NUMBER
LOCAL_ORDER_NO
NUMBER
DEQUEUE_MSGID
RAW(16)
CHAIN_NO
NUMBER
SENDER_NAME
VARCHAR2(30)
CSCN
NUMBER
SENDER_ADDRESS
VARCHAR2(1024)
DSCN
NUMBER
SENDER_PROTOCOL
NUMBER
ENQ_TIME
DATE
USER_DATA
TYPE1
ENQ_UID
VARCHAR2(30)
USER_PROP
SYS.ANYDATA
ENQ_TID
VARCHAR2(30)
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Database Objects
56

The AQ$_<queue_table_name>_P table has one primary key index on
 Q_NAME
 MSGID

Two view definitions are also updated when the first buffered message is
enqueued:
 AQ$<queue_table_name>
 e.g. AQ$QT3
 reports all messages in persistent and buffered queues
 AQ$_<queue_table_name>_F
 e.g. AQ$_QT3_F
 reports all messages that have not yet been dequeued in both
persistent and buffered queues
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Database Objects


The queue monitor slaves write spilled messages to
AQ$_<queue_table_name>_P
 Rows are inserted individually; no array operation is used
For example
INSERT INTO "us01"."aq$_qt3_p"
(
q_name, msgid, corrid, priority,state, delay, expiration, time_manager_info,
local_order_no, chain_no, enq_time, step_no, enq_uid, enq_tid, retry_count,
exception_qschema, exception_queue, recipient_key, dequeue_msgid,
user_data, sender_name, sender_address, sender_protocol, dscn, cscn
)
VALUES
(:1,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,0,:15,:16,:17,:18,:19,:20,:21,:22,:23,:24)



Messages are asynchronously deleted from AQ$_<queue_table_name>_P by
queue monitor slaves
Messages are deleted using an array size of 32
For example
DELETE FROM us01.aq$_qt24_p WHERE q_name = :1 AND msgid = :2
57
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Database Objects


58
AQ$_<table_queue_name>_D contains the following columns
Column Name
Data Type
OID
NUMBER
MSGNUM
NUMBER
MSGID
RAW(16)
SUB
NUMBER
SEQNUM
NUMBER
RSUBS
SYS.AQ$_RECIPIENTS
The RSUBS column is stored as a LOB
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Spillage

59
If flow control is enabled then number of buffered messages that can be
enqueued on any queue is limited
 Subsequent attempts to enqueue messages will be rejected

Set _BUFQ_STOP_FLOW_CONTROL parameter to TRUE to disable flow
control completely

Limited to
 5000 buffered messages
 15000 captured messages

Can be overridden in 10.2.0.3 by applying Patch 5093060 and setting
 Event 10867 for buffered messages (level is # messages)
 Event 10868 for captured messages (level is # messages)

Can be fixed in 10.2.0.4 onwards by setting:
 _BUFFERED_PUBLISHER_FLOW_CONTROL_THRESHOLD
 _CAPTURED_PUBLISHER_FLOW_CONTROL_THRESHOLD
© 2008 Julian Dyke
juliandyke.com
Buffered Messages
Database Objects

60
For a multiple consumer queue the following objects will be created when the
first buffered message is enqueued:
Object ID
Object Name
Object Type
72638
AQ$_QT3_P
TABLE
72639
SYS_LOB0000072638C00032$$
LOB
72640
SYS_IL0000072638C00032$$
LOB INDEX
72641
SYS_C0010003
INDEX
72642
AQ$_QT3_D
TABLE
72643
SYS_IOT_OVER_72642
TABLE
72644
SYS_LOB0000072642C00006$$
LOB
72645
SYS_IL0000072642C00006$$
INDEX
72646
SYS_IOT_TOP_72642
INDEX
© 2008 Julian Dyke
juliandyke.com
Performance
Elapsed Times
Enqueue
No Commit
61
Dequeue
Commit
No Commit
Commit
Single Consumer
PERSISTENT
ON COMMIT
4.77
10.99
5.75
9.62
Single Consumer
PERSISTENT
IMMEDIATE
10.80
11.41
8.77
9.78
Single Consumer
BUFFERED
IMMEDIATE
2.32
2.60
1.53
2.13
Single Consumer
PERSISTENT
ON COMMIT
VARRAY(10) OF TYPE1
0.66
1.38
1.00
1.35
Multi Consumer
PERSISTENT
ON COMMIT
2 recipients
6.40
14.45
6.36
11.20
Multi Consumer
PERSISTENT
ON COMMIT
2 subscribers
6.02
14.59
6.54
11.40
10000 TYPE1 messages enqueued then 10000 messages dequeued. Average of 5 runs. Oracle 10.2 on RHEL4.5
x86
© 2008 Julian Dyke
juliandyke.com
Performance
Redo Generation
Enqueue
No Commit
Dequeue
Commit
No Commit
Commit
Single Consumer
PERSISTENT
ON COMMIT
9223
15491
10806
15521
Single Consumer
PERSISTENT
IMMEDIATE
15165
15485
14936
14904
Single Consumer
BUFFERED
IMMEDIATE
0
0
0
0
1211
1831
1381
1832
Multi Consumer
PERSISTENT
ON COMMIT
2 recipients
16459
23324
8102
12521
Multi Consumer
PERSISTENT
ON COMMIT
2 subscribers
15832
23404
7934
12953
Single Consumer
PERSISTENT
ON COMMIT
VARRAY(10) OF TYPE1
10 TYPE1 messages enqueued then 10 messages dequeued. Average of 5 runs. Oracle 10.2 on RHEL4.5 x86
62
© 2008 Julian Dyke
juliandyke.com
Conclusion
63

Several single queues may be more efficient than
 Multiple recipients
 Multiple subscribers

Use ON_COMMIT visibility where possible
 No transaction overhead for queuing operations
 Reduces undo / redo generation
 IMMEDIATE is much more expensive

Buffered messages give best performance
 Provided they do not spill regularly

Array payloads are very efficient
 Message overhead is reduced
© 2008 Julian Dyke
juliandyke.com
Thank you for your interest
[email protected]
64
© 2008 Julian Dyke
juliandyke.com