Могу ли я получить строки из SQLAlchemy, которые представляют собой простые массивы, а не словари? - PullRequest
3 голосов
/ 18 марта 2009

Я пытаюсь оптимизировать некоторый код Python. Профилировщик говорит мне, что _get_col () SQLAlchemy - это то, что убивает производительность. Код выглядит примерно так:

lots_of_rows = get_lots_of_rows()
for row in lots_of_rows:
    if row.x == row.y:
        print row.z

Я собирался пройтись по коду и сделать его более похожим на это ...

lots_of_rows = get_lots_of_rows()
for row in lots_of_rows:
    if row[0] == row[1]:
        print row[2]

... но я нашел некоторую документацию, которая, кажется, указывает на то, что при доступе к объектам строк, таким как массивы, вы все еще тянете ключи словаря. Другими словами, объект строки выглядит так:

'x': (x object)
'0': (x object)
'y': (y object)
'1': (y object)
'z': (z object)
'2': (z object)

Если это так, я сомневаюсь, что у меня будет какое-либо улучшение производительности при доступе к столбцам по номеру, а не по имени. Есть ли способ заставить SA возвращать результаты в виде списка кортежей или списка списков, а не списка словарей? С другой стороны, кто-нибудь может предложить какие-либо другие оптимизации?

Ответы [ 4 ]

2 голосов
/ 18 марта 2009

Простите за очевидный ответ, но почему в вашем запросе нет row.x == row.y? Например:

mytable.select().where(mytable.c.x==mytable.c.y)

Должно дать вам огромный прирост производительности. Прочитайте остальную часть документации.

1 голос
/ 15 мая 2009

SQLAlchemy проксирует весь доступ к базовому курсору базы данных для сопоставления именованных ключей с позициями в кортеже строк и выполнения любых необходимых преобразований типов. Базовая реализация довольно сильно оптимизирована, кэшируя практически все. Рассматривая дизассемблирование, кажется, что единственным способом дальнейшей оптимизации является отказ от расширяемости и избавление от пары поисков атрибутов или прибегание к динамической генерации кода для получения меньшего выигрыша или для получения большего, реализации соответствующих классов ResultProxy и RowProxy в C.

Некоторое быстрое профилирование показывает, что на моем ноутбуке накладные расходы составляют около 5us. Это будет важно, если с данными будет выполняться только тривиальная обработка. В таких случаях было бы разумно опуститься до уровня dbapi. Это не означает, что вы должны потерять функциональность построения запросов SQLAlchemy. Просто выполните оператор, как обычно, и получите курсор dbapi из ResultProxy, открыв result.cursor.cursor. (result.cursor является объектом SQLAlchemy CursorFairy). Затем вы можете использовать обычные методы dbapi fetchall (), fetchone () и fetchmany ().

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

1 голос
/ 18 марта 2009

Я думаю row.items() это то, что вы ищете. Возвращает список кортежей (ключ, значение) для строки.

Ссылка

0 голосов
/ 18 марта 2009

Вы должны опубликовать результаты своего профилировщика, а также трассировки стека вокруг вызова '_get_col', чтобы мы знали, какой _get_col вызывается. (и является ли _get_col действительно узким местом).

Я посмотрел на источник sqlalchemy, похоже, он каждый раз вызывает 'lookup_key' (в engine / base.py), и похоже, что он кэширует значение столбца локально, я полагаю, лениво (через PopulateDict).

Вы можете попытаться обойти это, напрямую используя row .__ props (не рекомендуется, так как он закрыт), может быть, вы можете использовать row.cursor, но похоже, что вы многого выиграете, обходя sqlalchemy (кроме генерации sql) и работая напрямую / курсор.

- J

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...