Skip to Main Content
  • Questions
  • Clarification regarding Oracle Advanced Queue partitioning/ parallel processing methods.

Breadcrumb

Question and Answer

Chris Saxon

Thanks for the question, Avinash.

Asked: April 06, 2025 - 8:51 am UTC

Last updated: April 11, 2025 - 12:37 pm UTC

Version: 19c

Viewed 100+ times

You Asked

Use Case: We are implementing partitioning in the AQ to enable batch processing with array dequeue while ensuring:

1. Ordering maintained per partition (FIFO).

2. Possibility to Array Deqeue on Application side. ( Unless provided a more performant solution ).

Approach & Observation:

1. We partition messages using a sort of partition_id, ( User defined in queue table) assigning each message a hash (eg: 1-5 ) at enqueue time.

PROCEDURE Enqueu_Event_(
   partition_id_ NUMBER, 
   message_content_ JSON_OBJECT_T
) IS    
   queue_payload_ TEST_PAYLOAD_TYPE;

   r_enqueue_options_    DBMS_AQ.ENQUEUE_OPTIONS_T;
   r_message_properties_ DBMS_AQ.MESSAGE_PROPERTIES_T;
   v_message_handle_     RAW(16);
BEGIN
   -- Construct payload with provided partition_id
   queue_payload_ := TEST_PAYLOAD_TYPE(partition_id_, message_content_.to_blob());

   -- Enqueue message
   DBMS_AQ.ENQUEUE(
      queue_name         => OUT_QUEUE_NAME, 
      enqueue_options    => r_enqueue_options_, 
      message_properties => r_message_properties_,
      payload           => queue_payload_, 
      msgid             => v_message_handle_
   );

   COMMIT;
END Publish_Event_;
/


2. On the consumer side ( Polling ), we use AQDequeueOptions with:

dequeueOpts.navigation := DBMS_AQ.FIRST_MESSAGE; to fetch the first message for ordering.
deqeueOpts.deq_condition := ("partition_id = 1") to filter messages per partition.
PROCEDURE Dequeue_Events_(
   partition_id_ NUMBER
) IS    
   r_dequeue_options_    DBMS_AQ.DEQUEUE_OPTIONS_T;
   r_message_properties_ DBMS_AQ.MESSAGE_PROPERTIES_ARRAY_T;
   v_message_handle_     DBMS_AQ.MSGID_ARRAY_T;
   queue_payload_        TEST_PAYLOAD_TYPE; 
   batch_size_           CONSTANT PLS_INTEGER := 10; -- Adjust batch size as needed
BEGIN
   r_dequeue_options_.navigation := DBMS_AQ.FIRST_MESSAGE;
   r_dequeue_options_.dequeue_mode := DBMS_AQ.REMOVE;
-- Condition to filter by partition_id
   r_dequeue_options_.condition := 'tab.partition_id = ' || TO_CHAR(partition_id_);

   -- Array dequeue
   DBMS_AQ.DEQUEUE_ARRAY(
      queue_name         => IN_QUEUE_NAME, 
      dequeue_options    => r_dequeue_options_, 
      message_properties => r_message_properties_,
      payload            => queue_payload_, 
      num_msgs           => batch_size_, 
      msgid              => v_message_handle_
   );

   COMMIT;
END Dequeue_Events_;
/



Questions & Clarification:

Does setting DBMS_AQ.FIRST_MESSAGE; override the lack of ordering guarantee in deq_condition?
Can we reliably expect FIFO ordering per partition even when using deq_condition?
If not, what is the best approach to ensure parallel processing per partition while preserving order?
Is there a more efficient way to implement partitioned parallel dequeuing without sharded queues?

Links:

deq_condition ordering not guaranteed - https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/advanced-queuing-AQ-types.html#GUID-B11D312F-0EF5-4048-809B-630426E1E81A:~:text=dequeuing%20is%20undetermined.-,deq_condition,-A%20conditional%20expression
First message navigation → https://docs.oracle.com/en/database/oracle/oracle-database/19/arpls/advanced-queuing-AQ-types.html#GUID-B11D312F-0EF5-4048-809B-630426E1E81A:~:text=FIRST_MESSAGE_MULTI_GROUP

and Chris said...

From the Advanced Queuing User's Guide:

When a dequeue condition is used, the order of the messages dequeued is indeterminate, and the sort order of the queue is not honored.

https://docs.oracle.com/en/database/oracle/oracle-database/19/adque/aq-introduction.html#GUID-AA8621D3-88E6-460A-8EC4-8EE6F53DE56A__CHDIJCEE

So that looks like a clear "No" to your question on guaranteed ordering.

I'm not sure what the best option is for parallel processing, though I'd look into recipient lists. This allows you to specify who is allowed to dequeue a message. There's an overview of this on the same page linked above:

https://docs.oracle.com/en/database/oracle/oracle-database/19/adque/aq-introduction.html#GUID-5B6B013D-A646-4895-B929-970CBFB8C46D

Rating

  (1 rating)

Comments

Ordered Dequeuing requires business context in the partitioning

Johan Snyman, April 11, 2025 - 12:03 pm UTC

In order to retain sensible ordering of the dequeuing of the messages while implementing partitioning to achieve parallel processing, you'll need to introduce business context into how you partition the messages.

E.g. if the messages are processed in the context of customer, then you should setup the partitioning such that all the messages for a particular customer always go to the same partition. This will allow ordered processing of the messages within that partition to also order the messages in the context of the customer.
Chris Saxon
April 11, 2025 - 12:37 pm UTC

Good point

More to Explore

VLDB

If you are new to partitioning, check out Connor McDonald's introduction series here.

VLDB

Documentation set on VLDB and Partitioning.