cx_Oracle: Как мне перебрать набор результатов?

Есть несколько способов перебора набора результатов. Каковы компромиссы каждого?

3.08.2008 01:15:08
Есть исключения из этого, но общее практическое правило таково: если есть несколько способов сделать это, это, вероятно, потому что каждый способ подходит для разных ситуаций. В противном случае был бы только один путь.
Jeffrey Kemp 23.05.2012 02:13:52
3 ОТВЕТА
РЕШЕНИЕ

Каноническим способом является использование встроенного курсора итератора.

curs.execute('select * from people')
for row in curs:
    print row

Вы можете использовать, fetchall()чтобы получить все строки одновременно.

for row in curs.fetchall():
    print row

Это может быть удобно использовать для создания списка Python, содержащего возвращаемые значения:

curs.execute('select first_name from people')
names = [row[0] for row in curs.fetchall()]

Это может быть полезно для небольших наборов результатов, но может иметь плохие побочные эффекты, если набор результатов большой.

  • Вам нужно подождать, пока весь набор результатов будет возвращен вашему клиентскому процессу.

  • Вы можете съесть много памяти в вашем клиенте для хранения встроенного списка.

  • Python может занять некоторое время для создания и деконструкции списка, который вы в любом случае немедленно откажетесь.


Если вы знаете, что в наборе результатов возвращается одна строка, вы можете позвонить, fetchone()чтобы получить одну строку.

curs.execute('select max(x) from t')
maxValue = curs.fetchone()[0]

Наконец, вы можете зацикливаться на наборе результатов, выбирая по одной строке за раз. В общем, нет особого преимущества в этом по сравнению с использованием итератора.

row = curs.fetchone()
while row:
    print row
    row = curs.fetchone()
45
15.10.2016 20:47:11
о втором методе, что если вы используете SScursor? это все еще съест много памяти?
Sylvain 27.11.2009 10:50:17
Я думаю, что SScursor для MySQL. Но все, что имеет fetchall (), вероятно, будет иметь такое же использование памяти, поскольку оно возвращает список всех возвращаемых строк.
Mark Harrison 27.11.2009 20:25:49

Мой предпочтительный путь - итератор курсора, но сначала нужно установить свойство arraysize курсора.

curs.execute('select * from people')
curs.arraysize = 256
for row in curs:
    print row

В этом примере cx_Oracle будет извлекать строки из Oracle 256 строк одновременно, уменьшая количество сетевых обходов, которые необходимо выполнить

24
24.09.2008 02:51:00
В моих тестах (для базы данных, подключенной к локальной сети) это фактически показало идентичную (даже более медленную, за пару итераций) скорость по сравнению с повторным выполнением fetchone (). Я делал это с примерно 12000 записей ... Очень странно!
DKGasser 1.07.2011 16:01:39
Единственный способ, который я знаю, и я ни в коем случае не являюсь экспертом Oracle, заключается в том, что в этом случае ваш запрос возвращает типы больших символов (CLOB) или больших двоичных объектов (BLOB). AFAI. Поймите, для чтения этих объектов требуется еще один сетевой обход на сервер БД для каждой записи; Это означает, что с fetchmany вы получите худшее из обоих миров.
asmoore82 5.11.2015 20:31:26
Для cx_Oracle, подключаясь к базе данных 12c со стандартными типами столбцов (без сабов и т. Д.), Я получаю ускорение, но только если я устанавливаю arraysize перед выполнением запроса. Точные числа, очевидно, будут в значительной степени зависеть от контекста, но, чтобы дать представление о порядке изменения величины, мой запрос (возвращающий 5 столбцов) с arraysize = 50 (по умолчанию) дает 3,75 мкс на строку. Уменьшение массива до 1 дает 70us. Увеличение массива до 1000 дает 800 нс
FredL 6.07.2016 09:39:17
@FredL Я вижу нечто подобное. Это имеет значение только тогда, когда установлено до executeвызова.
axiom 11.12.2017 03:15:00

psyco-pgКажется, есть и способ сделать это ... Из того, что я понял, похоже, создается словарь-прокси строк для сопоставления поиска ключа с блоком памяти, возвращаемым запросом. В этом случае получение полного ответа и работа с аналогичной фабрикой прокси по строкам кажется полезной идеей. Если подумать, это похоже на Lua, а не на Python.

Кроме того, это должно быть применимо ко всем интерфейсам DBAPI2.0 PEP-249 , а не только к Oracle, или вы имели в виду просто самое быстрое использование Oracle ?

6
24.08.2008 17:28:26