If
you are working with a partitioned Oracle table, it is recommended
that you let the Oracle engine partition the table for you. The Oracle
engine gathers all partition information needed to perform a threaded
Read on the table.
A partitioned Oracle
table is a good candidate for a threaded Read because each partition
in the table can be read in parallel with little contention for disk
resources. If the Oracle engine determines that the table is partitioned,
it makes the same number of connections to the server as there are
partitions, as long as the maximum number of threads that are allowed
is higher than the number of partitions. Each connection retrieves
rows from a single partition.
If the value of the
maximum number of allowed threads is less than the number of partitions
on the table, a single connection reads multiple partitions. Each
connection retrieves rows from a single partition or multiple partitions.
However, you can use the DB_ONE_CONNECT_PER_THREAD= data set option
so that there is only one connection per thread.
The following example
shows how to do this. First, create the SALES table in Oracle.
CREATE TABLE SALES (acct_no NUMBER(5),
acct_name CHAR(30), amount_of_sale NUMBER(6), qtr_no INTEGER)
PARTITION BY RANGE (qtr_no)
(PARTITION sales1 VALUES LESS THAN (2) TABLESPACE ts0,
PARTITION sales2 VALUES LESS THAN (2) TABLESPACE ts1,
PARTITION sales3 VALUES LESS THAN (2) TABLESPACE ts2,
PARTITION sales4 VALUES LESS THAN (2) TABLESPACE ts3)
Performing a threaded
Read on this table with the following code, SAS makes four separate
connections to the Oracle server and each connection reads from each
partition. Turning on SASTRACE= shows the SQL that is generated for
each connection.
libname x oracle user=testuser path=oraserver;
data new;
set x.SALES (DBSLICEPARM=(ALL,10));
run;
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES2)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES3)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES1)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES4)
Using the following
code, SAS instead makes two separate connections to the Oracle server
and each connection reads from two different partitions.
libname x oracle user=testuser path=oraserver;
data new;
set x.SALES (DBSLICEPARM=(ALL,2));
run;
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES2) UNION ALL SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE",
"QTR_NO" FROM SALES partition (SALES3)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES1) UNION ALL SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE",
"QTR_NO" FROM SALES partition (SALES4)
Using DB_ONE_CONNECT_PER_THREAD=NO,
however, you can override the default behavior of limiting the number
of connections to the number of threads. As shown below, SAS makes
four separate connections to the Oracle server and each connection
reads from each of the partition.
libname x oracle user=testuser path=oraserver;
data new;
set x.SALES (DBSLICEPARM=(ALL,2) DB_ONE_CONNECT_PER_THREAD=NO );
run;
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES2)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES3)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES1)
ORACLE: SELECT "ACCT_NO","ACCT_NAME", "AMOUNT_OF_SALE", "QTR_NO" FROM SALES
partition (SALES4)
The second parameter
of the DBSLICEPARM= LIBNAME option determines the number of threads
to read the table in parallel. The number of partitions on the table,
the maximum number of allowed threads, and the value of DB_ONE_CONNECT_PER_THREAD=
determine the number of connections to the Oracle server for retrieving
rows from the table.