Documentation improvements.
This commit is contained in:
parent
a21e06a60c
commit
b4443c0f9f
|
@ -9,9 +9,8 @@ Overview
|
||||||
|
|
||||||
To use cx_Oracle 8 with Python and Oracle Database you need:
|
To use cx_Oracle 8 with Python and Oracle Database you need:
|
||||||
|
|
||||||
- Python 3.5 and higher. Older versions of cx_Oracle may work with older
|
- Python 3.5 and higher. Older versions of cx_Oracle may work with older
|
||||||
versions of Python, for example see :ref:`Installing cx_Oracle in Python 2
|
versions of Python.
|
||||||
<python2>`
|
|
||||||
|
|
||||||
- Oracle Client libraries. These can be from the free `Oracle Instant
|
- Oracle Client libraries. These can be from the free `Oracle Instant
|
||||||
Client
|
Client
|
||||||
|
@ -40,8 +39,8 @@ Quick Start cx_Oracle Installation
|
||||||
- Install `Python <https://www.python.org/downloads>`__ 3, if not already
|
- Install `Python <https://www.python.org/downloads>`__ 3, if not already
|
||||||
available. On macOS you must always install your own Python.
|
available. On macOS you must always install your own Python.
|
||||||
|
|
||||||
Python 3.5 and higher are supported by cx_Oracle 8. For Python 2, see
|
Python 3.5 and higher are supported by cx_Oracle 8. If you use Python 2,
|
||||||
:ref:`Installing cx_Oracle in Python 2 <python2>`.
|
then the older cx_Oracle 7.3 will install.
|
||||||
|
|
||||||
- Install cx_Oracle from `PyPI
|
- Install cx_Oracle from `PyPI
|
||||||
<https://pypi.org/project/cx-Oracle/>`__ with:
|
<https://pypi.org/project/cx-Oracle/>`__ with:
|
||||||
|
@ -794,12 +793,13 @@ If you are upgrading from cx_Oracle 5 note these installation changes:
|
||||||
Installing cx_Oracle in Python 2
|
Installing cx_Oracle in Python 2
|
||||||
================================
|
================================
|
||||||
|
|
||||||
To install cx_Oracle in Python 2, use a command like::
|
cx_Oracle 7.3 was the last version with support for Python 2.
|
||||||
|
|
||||||
|
If you install cx_Oracle in Python 2 using the commands provided above, then
|
||||||
|
cx_Oracle 7.3 will be installed. This is equivalent to using a command like::
|
||||||
|
|
||||||
python -m pip install cx_Oracle==7.3 --upgrade --user
|
python -m pip install cx_Oracle==7.3 --upgrade --user
|
||||||
|
|
||||||
cx_Oracle 7.3 was the last version with support for Python 2.
|
|
||||||
|
|
||||||
For other installation options such as installing through a proxy, see
|
For other installation options such as installing through a proxy, see
|
||||||
instructions above. Make sure the Oracle Client libraries are in the system
|
instructions above. Make sure the Oracle Client libraries are in the system
|
||||||
library search path because cx_Oracle 7 does not support the
|
library search path because cx_Oracle 7 does not support the
|
||||||
|
|
|
@ -91,61 +91,8 @@ already buffered in the Oracle Client libraries. Reducing round-trips helps
|
||||||
performance and scalability. An overhead of prefetching is the need for an
|
performance and scalability. An overhead of prefetching is the need for an
|
||||||
additional data copy from Oracle Client's prefetch buffers.
|
additional data copy from Oracle Client's prefetch buffers.
|
||||||
|
|
||||||
To tune queries that return an unknown number of rows, estimate the number of
|
Choosing values for ``arraysize`` and ``prefetchrows``
|
||||||
rows returned and start with an appropriate :attr:`Cursor.arraysize` value. The
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
default is 100. Then set :attr:`Cursor.prefetchrows` to the ``arraysize``
|
|
||||||
value. Do not make the sizes unnecessarily large. Keep ``arraysize`` as big,
|
|
||||||
or bigger than, ``prefetchrows``. Adjust the values as needed for performance,
|
|
||||||
memory and round-trip usage. An example is:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
cur = connection.cursor()
|
|
||||||
|
|
||||||
cur.prefetchrows = 1000
|
|
||||||
cur.arraysize = 1000
|
|
||||||
|
|
||||||
for row in cur.execute("SELECT * FROM very_big_table"):
|
|
||||||
print(row)
|
|
||||||
|
|
||||||
For a large quantity of rows or very "wide" rows on fast networks you may prefer
|
|
||||||
to leave ``prefetchrows`` at its default value of 2. The documentation in
|
|
||||||
:ref:`roundtrips` shows how to measure round-trips.
|
|
||||||
|
|
||||||
If you are fetching a fixed number of rows, start your tuning by setting
|
|
||||||
``arraysize`` to the number of expected rows, and set ``prefetchrows`` to one
|
|
||||||
greater than this value. (Adding one removes the need for a round-trip to check
|
|
||||||
for end-of-fetch). For example, if you are querying 20 rows, perhaps to
|
|
||||||
:ref:`display a page <rowlimit>` of data, set ``prefetchrows`` to 21 and
|
|
||||||
``arraysize`` to 20:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
cur = connection.cursor()
|
|
||||||
|
|
||||||
cur.prefetchrows = 21
|
|
||||||
cur.arraysize = 20
|
|
||||||
|
|
||||||
for row in cur.execute("""
|
|
||||||
SELECT last_name
|
|
||||||
FROM employees
|
|
||||||
ORDER BY last_name
|
|
||||||
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY"""):
|
|
||||||
print(row)
|
|
||||||
|
|
||||||
This will return all rows for the query in one round-trip.
|
|
||||||
|
|
||||||
If you know that a query returns just one row then set :attr:`Cursor.arraysize`
|
|
||||||
to 1 to minimize memory usage. The default prefetch value of 2 allows minimal
|
|
||||||
round-trips for single-row queries:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
cur = connection.cursor()
|
|
||||||
cur.arraysize = 1
|
|
||||||
cur.execute("select * from MyTable where id = 1"):
|
|
||||||
row = cur.fetchone()
|
|
||||||
print(row)
|
|
||||||
|
|
||||||
The best :attr:`Cursor.arraysize` and :attr:`Cursor.prefetchrows` values can be
|
The best :attr:`Cursor.arraysize` and :attr:`Cursor.prefetchrows` values can be
|
||||||
found by experimenting with your application under the expected load of normal
|
found by experimenting with your application under the expected load of normal
|
||||||
|
@ -153,31 +100,65 @@ application use. This is because the cost of the extra memory copy from the
|
||||||
prefetch buffers when fetching a large quantity of rows or very "wide" rows may
|
prefetch buffers when fetching a large quantity of rows or very "wide" rows may
|
||||||
outweigh the cost of a round-trip for a single cx_Oracle user on a fast network.
|
outweigh the cost of a round-trip for a single cx_Oracle user on a fast network.
|
||||||
However under production application load, the reduction of round-trips may help
|
However under production application load, the reduction of round-trips may help
|
||||||
performance and overall system scalability.
|
performance and overall system scalability. The documentation in
|
||||||
|
:ref:`round-trips <roundtrips>` shows how to measure round-trips.
|
||||||
|
|
||||||
Prefetching can also be enabled in an external :ref:`oraaccess.xml
|
Here are some suggestions for the starting point to begin your tuning:
|
||||||
<optclientfiles>` file, which may be useful for tuning an application when
|
|
||||||
modifying its code is not feasible. Setting the size in ``oraaccess.xml`` will
|
|
||||||
affect the whole application, so it should not be the first tuning choice.
|
|
||||||
|
|
||||||
One place where increasing ``arraysize`` is particularly useful is in copying
|
* To tune queries that return an unknown number of rows, estimate the number of
|
||||||
data from one database to another:
|
rows returned and start with an appropriate :attr:`Cursor.arraysize` value.
|
||||||
|
The default is 100. Then set :attr:`Cursor.prefetchrows` to the ``arraysize``
|
||||||
|
value. Do not make the sizes unnecessarily large. For example:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
# setup cursors
|
cur = connection.cursor()
|
||||||
sourceCursor = sourceConnection.cursor()
|
|
||||||
sourceCursor.arraysize = 1000
|
|
||||||
targetCursor = targetConnection.cursor()
|
|
||||||
|
|
||||||
# perform fetch and bulk insertion
|
cur.prefetchrows = 1000
|
||||||
sourceCursor.execute("select * from MyTable")
|
cur.arraysize = 1000
|
||||||
while True:
|
|
||||||
rows = sourceCursor.fetchmany()
|
for row in cur.execute("SELECT * FROM very_big_table"):
|
||||||
if not rows:
|
print(row)
|
||||||
break
|
|
||||||
targetCursor.executemany("insert into MyTable values (:1, :2)", rows)
|
Adjust the values as needed for performance, memory and round-trip usage. For
|
||||||
targetConnection.commit()
|
a large quantity of rows or very "wide" rows on fast networks you may prefer
|
||||||
|
to leave ``prefetchrows`` at its default value of 2. Keep ``arraysize`` as
|
||||||
|
big, or bigger than, ``prefetchrows``.
|
||||||
|
|
||||||
|
* If you are fetching a fixed number of rows, start your tuning by setting
|
||||||
|
``arraysize`` to the number of expected rows, and set ``prefetchrows`` to one
|
||||||
|
greater than this value. (Adding one removes the need for a round-trip to check
|
||||||
|
for end-of-fetch). For example, if you are querying 20 rows, perhaps to
|
||||||
|
:ref:`display a page <rowlimit>` of data, set ``prefetchrows`` to 21 and
|
||||||
|
``arraysize`` to 20:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
cur = connection.cursor()
|
||||||
|
|
||||||
|
cur.prefetchrows = 21
|
||||||
|
cur.arraysize = 20
|
||||||
|
|
||||||
|
for row in cur.execute("""
|
||||||
|
SELECT last_name
|
||||||
|
FROM employees
|
||||||
|
ORDER BY last_name
|
||||||
|
OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY"""):
|
||||||
|
print(row)
|
||||||
|
|
||||||
|
This will return all rows for the query in one round-trip.
|
||||||
|
|
||||||
|
* If you know that a query returns just one row then set :attr:`Cursor.arraysize`
|
||||||
|
to 1 to minimize memory usage. The default prefetch value of 2 allows minimal
|
||||||
|
round-trips for single-row queries:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
cur = connection.cursor()
|
||||||
|
cur.arraysize = 1
|
||||||
|
cur.execute("select * from MyTable where id = 1"):
|
||||||
|
row = cur.fetchone()
|
||||||
|
print(row)
|
||||||
|
|
||||||
In cx_Oracle, the ``arraysize`` and ``prefetchrows`` values are only examined
|
In cx_Oracle, the ``arraysize`` and ``prefetchrows`` values are only examined
|
||||||
when a statement is executed the first time. To change the values, create a new
|
when a statement is executed the first time. To change the values, create a new
|
||||||
|
@ -207,6 +188,30 @@ to 0:
|
||||||
function before cx_Oracle can return them to the application. Setting
|
function before cx_Oracle can return them to the application. Setting
|
||||||
``prefetchrows`` to 0 helps give a consistent flow of data to the application.
|
``prefetchrows`` to 0 helps give a consistent flow of data to the application.
|
||||||
|
|
||||||
|
Prefetching can also be enabled in an external :ref:`oraaccess.xml
|
||||||
|
<optclientfiles>` file, which may be useful for tuning an application when
|
||||||
|
modifying its code is not feasible. Setting the size in ``oraaccess.xml`` will
|
||||||
|
affect the whole application, so it should not be the first tuning choice.
|
||||||
|
|
||||||
|
One place where increasing ``arraysize`` is particularly useful is in copying
|
||||||
|
data from one database to another:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# setup cursors
|
||||||
|
sourceCursor = sourceConnection.cursor()
|
||||||
|
sourceCursor.arraysize = 1000
|
||||||
|
targetCursor = targetConnection.cursor()
|
||||||
|
|
||||||
|
# perform fetch and bulk insertion
|
||||||
|
sourceCursor.execute("select * from MyTable")
|
||||||
|
while True:
|
||||||
|
rows = sourceCursor.fetchmany()
|
||||||
|
if not rows:
|
||||||
|
break
|
||||||
|
targetCursor.executemany("insert into MyTable values (:1, :2)", rows)
|
||||||
|
targetConnection.commit()
|
||||||
|
|
||||||
.. _roundtrips:
|
.. _roundtrips:
|
||||||
|
|
||||||
Database Round-trips
|
Database Round-trips
|
||||||
|
@ -305,8 +310,8 @@ cache.
|
||||||
|
|
||||||
.. _clientresultcache:
|
.. _clientresultcache:
|
||||||
|
|
||||||
Client Result Cache
|
Client Result Caching
|
||||||
===================
|
=====================
|
||||||
|
|
||||||
cx_Oracle applications can use Oracle Database's `Client Result Cache
|
cx_Oracle applications can use Oracle Database's `Client Result Cache
|
||||||
<https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-35CB2592-7588-4C2D-9075-6F639F25425E>`__.
|
<https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-35CB2592-7588-4C2D-9075-6F639F25425E>`__.
|
||||||
|
@ -332,7 +337,7 @@ restarting the database, for example:
|
||||||
SQL> STARTUP FORCE
|
SQL> STARTUP FORCE
|
||||||
|
|
||||||
CRC can alternatively be configured in an :ref:`oraaccess.xml <optclientfiles>`
|
CRC can alternatively be configured in an :ref:`oraaccess.xml <optclientfiles>`
|
||||||
or :ref:`sqlnet.ora <optnetfiles>` file on the Node.js host, see `Client
|
or :ref:`sqlnet.ora <optnetfiles>` file on the Python host, see `Client
|
||||||
Configuration Parameters
|
Configuration Parameters
|
||||||
<https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-E63D75A1-FCAA-4A54-A3D2-B068442CE766>`__.
|
<https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-E63D75A1-FCAA-4A54-A3D2-B068442CE766>`__.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue