22 OCI Pipelining
Pipelining increases the overall throughput and responsiveness of the application. Starting with Oracle Database Release 23ai, pipelining feature is introduced to help the applications utilize the interleaving effectively and keep the server busy by overlapping the application requests, and the responses returned by the server.
See Also:
OCI Pipelining Functions22.1 Blocking and Non-Blocking Concepts
This section describes the blocking and non-blocking concepts.
Blocking functionality
All OCI functions that make a network round trip are request and response in nature. An application sends a request and waits for a response before sending another request.
For example, OCIStmtExecute()
function sends a request
to execute an SQL and waits for the response from the server. A single OCI function
is executed at a time. If another OCI function is invoked simultaneously without
completing the previous request, then the operation results in an error. This model
of execution leaves the server in idle state between the current response and the
next request. It also leaves the client in an idle state between the current request
and its response from the server.
Non-blocking functionality
Non-blocking functionality is helpful to applications as they benefit from using the interleaving to do some other operations during the idle time. This model improves the application responsiveness that is, the client idle time by allowing the application to choose what to do instead of blocking for the responses from the server.
22.2 Introduction to OCI Pipelining
This chapter introduces the pipelining functionality.
The fundamental idea of pipelining is to keep the server busy and allow an application to use the interleaving requests and responses appropriately.
The application keeps sending several requests, server builds up a queue and executes them one by one. The server sends the responses back to the client in the same order in which it received the requests.
Note:
As the pipeline does not read the responses so often, using the data from a previous SQL response as in-bind data to the subsequent request creates a dependency and breaks the pipeline.The following diagram shows the end-to-end depiction of a sample scenario in the pipeline:
- The OCI pipeline application is processing seven operations simultaneously as shown in the preceding diagram.
- The server processes the first request, the response to this request reaches the client. The response is now ready to be read.
- The second request is in the process of completion at the server end.
- The requests, three to six are queued at the server end and are yet to be processed by the server.
- The client is asynchronously sending the seventh request to the server.
OCIPipelineBegin()
: Indicates the start of the pipeline block of operations.OCIPipelineProcess()
: Processes an operation.OCIPipelineEnd()
: Indicates the end of the pipeline block of operations.
- The top half (send a request)
- The bottom half (receive a response)
The top half of the operation is the request sent to the server for
processing. The bottom half is the response received from the server. The response is
obtained using either OCIPipelineProcess()
or
OCIPipelineEnd()
function.
With this approach, all the OCI functions that support pipelining (for
example, OCIStmtExecute()
, OCIStmtFetch2()
) in the
pipeline operation block are implicitly pipelined.
Note:
In pipeline mode, it is the responsibility of the application to ensure that the dependency on two consecutive operations is resolved or avoided.Two adjacent blocks of pipeline operations are supported. The following is a sample code snippet:
OCIPipelineBegin();
OCIPipelineEnd();
;;;
OCIPipelineBegin();
OCIPipelineEnd();
OCIPipelineBegin();
OCIPipelineBegin();
OCIPipelineEnd();
OCIPipelineEnd();
Note:
Starting with Oracle Database Release 23ai, enhancements are being made to both the client and the server, to provide pipelining functionality.22.2.1 Enabling OCI Pipelining
This section describes how to enable pipelining for OCI APIs.
By default, OCI APIs are not available to an application for pipelining.
A new attribute, OCI_PIPELINE_ENABLE
, is introduced to enable
pipelining. The pipeline functionality is available only when the application sets
the attribute on the environment. Any call to OCI pipeline function without this
mode set, returns an error.
Syntax
boolean pipelineEnable = TRUE;
status = OCIAttrSet((dvoid *) envhp,
OCI_HTYPE_ENV,
(dvoid *) &sts,
(ub4) sizeof(sts),
OCI_ATTR_PIPELINE_ENABLE,
(OCIError *) errhp));
Most of the applications use OCI functions in a blocking or non-blocking
mode. OCI_ATTR_PIPELINE_ENABLE
attribute helps to avoid performance
regressions in blocking and non-blocking scenarios and acts like a switch to disable
pipelining in the OCI application.
22.3 Modes of Pipeline Operation
This section describes the different modes of pipeline operation.
The OCIPipelineBegin()
function marks the beginning of the pipelined
block of operations.
The modes of pipelined operations defines how the pipelined operations are executed. There are two levels of pipeline modes. Each level can set one of the two modes of execution.
- Operation level mode (
OCI_ATTR_PIPELINE_OP_MODE
): The server continues executing the operations even after one of the pipelined operations fails with an error, untilOCIPipelineEnd()
function is executed.Applications need to set the
OCI_ATTR_PIPELINE_OP_MODE
attribute on the handle ((svchp)
in the operation using theOCIAttrSet
attribute.Example:
ForOCIStmtExecute
, the following attribute is set:rc = OCIAttrSet((dvoid *) svchp, (ub4) OCI_HTYPE_SVC, (dvoid *) OCI_PIPELINE_CONT_ON_ERROR, (ub4) 0, (ub4) OCI_ATTR_PIPELINE_OP_MODE, (OCIError *) errhp); rc = OCIStmtExecute(svchp, stmthp, … , OCI_DEFAULT);
- Block-level mode (
OCI_PIPELINE_ABORT_ON_ERROR
): The pipeline operation aborts if an error is encountered while processing the pipelined block of operations.If any error is returned in any operation in a pipelined block of operations, then it aborts all the pipelined operations following that operation. All the operations till the
OCIPipelineEnd()
function returns an error to the client.The responses of the operations executed successfully before the failure of an operation are returned to the application. The operation that resulted in an error is also a valid operation. The error handle has more details on the error returned.
The following example shows the usage ofOCI_PIPELINE_ABORT_ON_ERROR
mode:
When the block level mode isrc = OCIPipelineBegin(svchp, cbk, cbkCtx, errhp, OCI_PIPELINE_ABORT_ON_ERROR);
OCI_PIPELINE_ABORT_ON_ERROR
this means the pipeline aborts if an error has encountered while processing the pipelined operations.The server returns an error (ORA-43610) for each operation until the end of the pipelined operations.
22.4 OCIPipelineOperation
OCIPipelineOperation is an opaque handle representing a pipelined operation in a pipeline block. OCIPipelineOperation contains the information of the OCI operation executed. An operation instance stores the parameters along with the states to complete the top (send request) and bottom (receive response) parts of the pipelined operations.
22.5 The Life Cycle of the OCI Pipeline Handle
This section describes the life cycle of the OCI pipeline handle.
OCI_PIPELINE_OP_SENT
. When a response
is received, it changes to OCI_PIPELINE_OP_READY
state. After the
operation is completed implicitly or explicitly, the registered callback is processed.
Note:
It is the responsibility of the application to keep the OCI call parameters valid until the bottom half (receive a response) of the operation is executed.OCIStmtExecute()
function has been
completed.
Note:
The identical outbind or define parameters are overridden after the bottom half (receive a response) of the operation.22.5.1 Status of the Pipeline Operation
This section describes how to obtain the status of the pipeline operation handle.
OCI_ATTR_PIPELINE_OP_STATUS
OCIAttrGet()
attribute. The value can be one of the
following:
OCI_PIPELINE_OP_READY
OCI_PIPELINE_OP_SENT
Note:
All the operation handles are freed after theOCIPipelineEnd()
operation is
executed.
22.6 OCI Pipeline Attributes
This section lists and describes the OCI pipeline attributes.
Following are the OCI pipeline attributes:
OCI_ATTR_PIPELINE_PROCESS_FIRST
Example 22-1 Example:
OCIPipelineOperationID first;
status = OCIAttrGet (svchp, OCI_HTYPE_SVC, &first, NULL,
OCI_ATTR_PIPELINE_PROCESS_LAST, errhp);
OCI_ATTR_PIPELINE_PROCESS_LAST
Example 22-2 Example:
OCIPipelineOperationID last;
status = OCIAttrGet (svchp, OCI_HTYPE_SVC, &last, NULL,
OCI_ATTR_PIPELINE_PROCESS_LAST, errhp);
OCI_ATTR_PIPELINE_DEPTH
Example 22-3 Example:
ub4 depth = 300;
status = OCIAttrSet (svchp, OCI_HTYPE_SVC, &depth, size of(depth), OCI_ATTR_PIPELINE_DEPTH, errhp);
OCI_ATTR_PIPELINE_HANDLE
Example 22-4 Example:
OCIStmt *updateHandle;
status = OCIAttrGet (operation, OCI_HTYPE_OPERATION, &updateHandle, NULL, OCI_ATTR_PIPELINE_HANDLE, errhp);
OCI_ATTR_PIPELINE_HANDLE_TYPE
Example 22-5 Example:
ub4 handleType = 0;status = OCIAttrGet (operation, OCI_HTYPE_OPERATION, &handleType, sizeof(handleType),
OCI_ATTR_PIPELINE_HANDLE_TYPE, errhp);
22.7 OCI Functions that Support Pipelining
Note:
- If
OCIStmtExecute()
,OCIStmtFetch()
, andOCIStmtFetch2()
requests include OCI objects, then they cannot be pipelined. OCITransCommit()
andOCITransRollback()
transaction requests pipelining functions support only local transactions.
OCIStmtExecute()
OCIStmtFetch()
OCIStmtFetch2()
OCITransCommit
OCITransRollback
OCILobAppend
OCILobArrayWrite
OCILobArrayRead
OCILobClose
OCILobCopy2
OCILobCreateTemporary
OCILobErase2
OCILobFileClose
OCILobFileCLoseAll
OCILobFileExists
OCILobFileIsOpen
OCILobFileOpen
OCILobFreeTemporary
OCILobGetChunkSize
OCILobGetLength2
OCILobOpen
OCILobIsOpen
OCILobLoadFromFile2
OCILobOpen
OCILobRead
OCILobRead2
OCILobTrim2
OCILobWrite
OCILobWrite2
OCILobWriteAppend2
22.8 When to Use Pipelining Functionality
This sections describes when to use pipelining functionality.
Pipelining functionality is useful when many small operations are being performed in rapid succession.
- OCIStmtExecute
- DDL, DML, Queries, PL/SQL, array inserts, DML with returning clause
- Exact fetch, multiple fetches
- Fetches from two different statement handles can be pipelined
Pipelining is more performant when the server is distant. That is, when the network latency is high.
Pipelining is less performant when operation has either implicit or explicit dependency on the result of the previous operation. In such cases, the client must introduce a synchronization point and wait for a complete client or server round-trip to get the results it needs.
- Implicit dependency: Execute a statement followed by a fetch on the same statement handle
- Explicit dependency: The result from a previous operation is used to bind the next operation execution