©
This document uses PHP Chinese website manual Release
(PHP 5, PECL OCI8 >= 1.1.0)
oci_set_prefetch — 设置预提取行数
$statement
[, int $rows
] )
在成功调用 oci_execute()
之后设定预提取的行数。rows
的默认值为 1。
Note:
在 PHP 5.0.0 之前的版本必须使用 ocisetprefetch() 替代本函数。该函数名仍然可用,为向下兼容作为 oci_set_prefetch() 的别名。不过其已被废弃,不推荐使用。
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
参见 oci8_.default_prefetch INI 选项。
statement
有效的 OCI8 报表标识符 由 oci_parse() 创建,被 oci_execute() 或 REF CURSOR statement 标识执行。
rows
The number of rows to be prefetched, >= 0
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
版本 | 说明 |
---|---|
PHP 5.3.2 (PECL OCI8 1.4) |
Before this release, rows must be >= 1.
|
PHP 5.3 (PECL OCI8 1.3.4) |
Before this release, prefetching was limited to the lesser
of rows rows and 1024
* rows bytes. The byte size
restriction has now been removed.
|
Example #1 Changing the default prefetch value for a query
<?php
$conn = oci_connect ( 'hr' , 'welcome' , 'localhost/XE' );
$stid = oci_parse ( $conn , 'SELECT * FROM myverybigtable' );
oci_set_prefetch ( $stid , 300 ); // Set before calling oci_execute()
oci_execute ( $stid );
echo "<table border='1'>\n" ;
while ( $row = oci_fetch_array ( $stid , OCI_ASSOC + OCI_RETURN_NULLS )) {
echo "<tr>\n" ;
foreach ( $row as $item ) {
echo " <td>" .( $item !== null ? htmlentities ( $item , ENT_QUOTES ) : " " ). "</td>\n" ;
}
echo "</tr>\n" ;
}
echo "</table>\n" ;
oci_free_statement ( $stid );
oci_close ( $conn );
?>
Example #2 Changing the default prefetch for a REF CURSOR fetch
<?php
$conn = oci_connect ( 'hr' , 'welcome' , 'localhost/XE' );
$stid = oci_parse ( $conn , 'BEGIN myproc(:rc); END;' );
$refcur = oci_new_cursor ( $conn );
oci_bind_by_name ( $stid , ':rc' , $refcur , - 1 , OCI_B_CURSOR );
oci_execute ( $stid );
// Change the prefetch before executing the cursor.
// REF CURSOR prefetching works when PHP is linked with Oracle 11gR2 Client libraries
oci_set_prefetch ( $refcur , 200 );
oci_execute ( $refcur );
echo "<table border='1'>\n" ;
while ( $row = oci_fetch_array ( $refcur , OCI_ASSOC + OCI_RETURN_NULLS )) {
echo "<tr>\n" ;
foreach ( $row as $item ) {
echo " <td>" .( $item !== null ? htmlentities ( $item , ENT_QUOTES ) : " " ). "</td>\n" ;
}
echo "</tr>\n" ;
}
echo "</table>\n" ;
oci_free_statement ( $refcur );
oci_free_statement ( $stid );
oci_close ( $conn );
?>
If PHP OCI8 fetches from a REF CURSOR and then passes the REF
CURSOR back to a second PL/SQL procedure for further processing,
then set the REF CURSOR prefetch count to 0
to
avoid rows being "lost" from the result set. The prefetch value is
the number of extra rows fetched in each OCI8 internal request to
the database, so setting it to 0
means only
fetch one row at a time.
Example #3 Setting the prefetch value when passing a REF CURSOR back to Oracle
<?php
$conn = oci_connect ( 'hr' , 'welcome' , 'localhost/orcl' );
// get the REF CURSOR
$stid = oci_parse ( $conn , 'BEGIN myproc(:rc_out); END;' );
$refcur = oci_new_cursor ( $conn );
oci_bind_by_name ( $stid , ':rc_out' , $refcur , - 1 , OCI_B_CURSOR );
oci_execute ( $stid );
// Display two rows, but don't prefetch any extra rows otherwise
// those extra rows would not be passed back to myproc_use_rc().
// A prefetch value of 0 is allowed in PHP 5.3.2 and PECL OCI8 1.4
oci_set_prefetch ( $refcur , 0 );
oci_execute ( $refcur );
$row = oci_fetch_array ( $refcur );
var_dump ( $row );
$row = oci_fetch_array ( $refcur );
var_dump ( $row );
// pass the REF CURSOR to myproc_use_rc() to do more data processing
// with the result set
$stid = oci_parse ( $conn , 'begin myproc_use_rc(:rc_in); end;' );
oci_bind_by_name ( $stid , ':rc_in' , $refcur , - 1 , OCI_B_CURSOR );
oci_execute ( $stid );
?>
Note:
In PHP versions before 5.0.0 use ocisetprefetch() instead. 在当前版本中,旧的函数名还可以被使用,但已经被废弃并不建议使用。
[#1] bmichael at goldparrot dot com [2003-01-04 15:00:59]
If your are using Oracle's OCI libraries, on any project, which PHP does, you can use this limit.
I have done network level testing on the effect of this parameter. It does improved efficiency. Big Time.
Oracle uses SQL*Net as the transport mechanism for data between your connection and the database. That is why you must setup Oracle properly.
This parameter tells SQL*NET to Buffer more results. When SQL*NET (at the server) gets a request for data, it bundles up X rows (1,2,3,1000, etc) for transport. It sends the appropriate SQL*NET headers back to the client, Waits for an ACK then begins sending data in MTU sized chunks (ethernet is something like 1500 bytes and ATM's WANS are around 1000 bytes). The chunk size can also be tuned in SQL*NET, but with much less improvements.
TCP/IP then takes the data across the wire, breaking it up into multiple TCP/IP packets.
Once the exchange is done, the SQL*NET client sends an
ACK back to the SQL*NET Listener (the Oracle Server) and the transaction is complete.
Each round trip, SQL*NET looks up inside the server memory (UGA - user global area) to find the query results. It then grabs the rows necessary to send. If it is one row, versus 1000 rows. The process is the same.
There is much I could tell you on how the Database itself reacts. If you can significantly lessen the amount of round trips you are making... WOW.
For more info on Oracle OCI go to http://otn.oracle.com