@@ -130,93 +130,6 @@ This code ensures that, once the block is completed, the cursor is closed and
130
130
resources have been reclaimed by the database. In addition, any attempt to use
131
131
the variable ``cursor `` outside of the block will simply fail.
132
132
133
- .. _tuningfetch :
134
-
135
- Tuning Fetch Performance
136
- ------------------------
137
-
138
- For best performance, the cx_Oracle :attr: `Cursor.arraysize ` value should be set
139
- before calling :meth: `Cursor.execute() `. The default value is 100. For queries
140
- that return a large number of rows, increasing ``arraysize `` can improve
141
- performance because it reduces the number of :ref: `round-trips <roundtrips >` to
142
- the database. However increasing this value increases the amount of memory
143
- required. The best value for your system depends on factors like your network
144
- speed, the query row size, and available memory. An appropriate value can be
145
- found by experimenting with your application.
146
-
147
- Regardless of which fetch method is used to get rows, internally all rows are
148
- fetched in batches corresponding to the value of ``arraysize ``. The size does
149
- not affect how, or when, rows are returned to your application (other than being
150
- used as the default size for :meth: `Cursor.fetchmany() `). It does not limit the
151
- minimum or maximum number of rows returned by a query.
152
-
153
- Along with tuning ``arraysize ``, make sure your `SQL statements are optimal
154
- <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=TGSQL> `_ and avoid
155
- selecting columns that are not required by the application. For queries that do
156
- not need to fetch all data, use appropriate ``WHERE `` clauses such as a
157
- :ref: `row limiting clause <rowlimit >` to reduce the number of rows processed by
158
- the database. For small, mostly static, lookup tables enable :ref: `Client Result
159
- Caching <crc>` to avoid round-trips between cx_Oracle and the database. For
160
- queries that return large data or a large number of rows, or when using a slow
161
- network, tune the network `Session Data Unit (SDU) and socket buffer sizes
162
- <https://static.rainfocus.com/oracle/oow19/sess/1553616880266001WLIh/PF/OOW19_Net_CON4641_1569022126580001esUl.pdf> `__.
163
-
164
- An example of setting ``arraysize `` is:
165
-
166
- .. code-block :: python
167
-
168
- cur = connection.cursor()
169
- cur.arraysize = 500
170
- for row in cur.execute(" select * from MyTable" ):
171
- print (row)
172
-
173
- One place where increasing ``arraysize `` is particularly useful is in copying
174
- data from one database to another:
175
-
176
- .. code-block :: python
177
-
178
- # setup cursors
179
- sourceCursor = sourceConnection.cursor()
180
- sourceCursor.arraysize = 1000
181
- targetCursor = targetConnection.cursor()
182
- targetCursor.arraysize = 1000
183
-
184
- # perform fetch and bulk insertion
185
- sourceCursor.execute(" select * from MyTable" )
186
- while True :
187
- rows = sourceCursor.fetchmany()
188
- if not rows:
189
- break
190
- targetCursor.executemany(" insert into MyTable values (:1, :2)" , rows)
191
- targetConnection.commit()
192
-
193
- If you know that a query returns a small number of rows then you should reduce
194
- the value of ``arraysize ``. For example if you are fetching only one row, then
195
- set ``arraysize `` to 1:
196
-
197
- .. code-block :: python
198
-
199
- cur = connection.cursor()
200
- cur.arraysize = 1
201
- cur.execute(" select * from MyTable where id = 1" ):
202
- row = cur.fetchone()
203
- print (row)
204
-
205
- In cx_Oracle, the ``arraysize `` value is only examined when a statement is
206
- executed the first time. To change the ``arraysize `` for a repeated statement,
207
- create a new cursor:
208
-
209
- .. code-block :: python
210
-
211
- array_sizes = (10 , 100 , 1000 )
212
- for size in array_sizes:
213
- cursor = connection.cursor()
214
- cursor.arraysize = size
215
- start = time.time()
216
- cursor.execute(sql).fetchall()
217
- elapsed = time.time() - start
218
- print (" Time for" , size, elapsed, " seconds" )
219
-
220
133
.. _querymetadata :
221
134
222
135
Query Column Metadata
@@ -808,72 +721,3 @@ SDO_GEOMETRY <spatial>` object:
808
721
cur = connection.cursor()
809
722
cur.setinputsizes(typeObj)
810
723
cur.execute(" insert into sometable values (:1)" , [None ])
811
-
812
- .. _roundtrips :
813
-
814
- Database Round-trips
815
- ====================
816
-
817
- A round-trip is defined as the trip from the Oracle Client libraries (:ref: `used by
818
- cx_Oracle <archfig>`) to the database and back. Along with tuning an application's
819
- architecture and tuning its SQL statements, a general performance and
820
- scalability goal is to minimize `round-trips
821
- <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-9B2F05F9-D841-4493-A42D-A7D89694A2D1> `__.
822
-
823
- Some general tips for reducing round-trips are:
824
-
825
- - Tune :attr: `Cursor.arraysize `, see :ref: `Tuning Fetch Performance <tuningfetch >`.
826
- - Use :meth: `Cursor.executemany() ` for optimal DML execution, see :ref: `Batch Statement Execution and Bulk Loading <batchstmnt >`.
827
- - Only commit when necessary. Use :attr: `Connection.autocommit ` on the last statement of a transaction.
828
- - For connection pools, use a callback to set connection state, see :ref: `Session CallBacks for Setting Pooled Connection State <sessioncallback >`.
829
- - Make use of PL/SQL procedures which execute multiple SQL statements instead of executing them individually from cx_Oracle.
830
- - Use scalar types instead of :ref: `Oracle named object types <fetchobjects >`
831
- - Avoid overuse of :meth: `Connection.ping() `.
832
-
833
- Oracle's `Automatic Workload Repository (AWR)
834
- <https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-56AEF38E-9400-427B-A818-EDEC145F7ACD> `__
835
- reports show 'SQL*Net roundtrips to/from client' and are useful for finding the
836
- overall behavior of a system.
837
-
838
- Sometimes you may wish to find the number of round-trips used for a
839
- specific application. Snapshots of the ``V$SESSTAT `` view taken before
840
- and after doing some work can be used for this.
841
-
842
- First, find the session id of the current connection:
843
-
844
- .. code-block :: python
845
-
846
- cursor.execute(" select sys_context('userenv','sid') from dual" )
847
- sid, = cursor.fetchone();
848
-
849
- This can be used with ``V$SESSTAT `` to find the current number of round-trips.
850
- A second connection should be used to avoid affecting the count. If your user
851
- does not have access to the V$ views, then use a SYSTEM connection:
852
-
853
- .. code-block :: python
854
-
855
- def getRT (conn , sid ):
856
- cursor = conn.cursor()
857
- cursor.execute(
858
- """ SELECT ss.value
859
- FROM v$sesstat ss, v$statname sn
860
- WHERE ss.sid = :sid
861
- AND ss.statistic# = sn.statistic#
862
- AND sn.name LIKE '%r oundtrip%c lient%'""" , sid = sid)
863
- rt, = cursor.fetchone();
864
- return rt
865
-
866
- The main part of a benchmark application can perform "work" and use ``getRT() ``
867
- to calculate the number of round-trips the work required:
868
-
869
- .. code-block :: python
870
-
871
- rt = getRT(systemconn, sid)
872
-
873
- cursor = conn.cursor()
874
- cursor.execute(" select * from dual" )
875
- row = cursor.fetchone()
876
-
877
- rt = getRT(systemconn, sid) - rt
878
-
879
- print (" Round-trips" , rt)
0 commit comments