3

我正在尝试优化一些 Python 代码。探查器告诉我 SQLAlchemy 的 _get_col() 是杀死性能的原因。代码看起来像这样:

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

4 回答 4

2

原谅显而易见的答案,但为什么您的查询中没有 row.x == row.y ?例如:

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

应该会给您带来巨大的性能提升。阅读文档的其余部分。

于 2009-03-17T22:33:20.943 回答
1

我想row.items()这就是你要找的。它返回该行的 (key, value) 元组列表。

关联

于 2009-03-17T21:25:26.333 回答
1

SQLAlchemy 代理对底层数据库游标的所有访问,以将命名键映射到行元组中的位置并执行任何必要的类型转换。底层实现经过了相当程度的优化,几乎缓存了所有内容。查看反汇编,进一步优化的唯一方法似乎是放弃可扩展性并摆脱几个属性查找,或者诉诸动态代码生成以获得较小的收益,或者为了获得更多收益,实现相应的 ResultProxy 和 RowProxy 类C。

一些快速分析表明,在我的笔记本电脑上每次查找的开销约为 5us。如果只对数据进行微不足道的处理,那将很重要。在这种情况下,下降到 dbapi 级别可能是合理的。这并不意味着您必须失去 SQLAlchemy 的查询构建功能。只需像往常一样执行该语句,然后ResultProxy通过访问result.cursor.cursor. (result.cursor是一个 SQLAlchemy CursorFairy 对象)然后您可以使用常规的 dbapi fetchall()、fetchone() 和 fetchmany() 方法。

但是,如果您确实在进行琐碎的处理,那么这样做可能会很有用,或者至少是数据库服务器上的过滤部分。您可能会失去数据库的可移植性,但这可能不是问题。

于 2009-05-14T22:37:46.313 回答
0

您应该在 '_get_col' 调用周围发布分析器结果以及堆栈跟踪,以便我们知道正在调用哪个 _get_col。(以及 _get_col 是否真的是瓶颈)。

我查看了 sqlalchemy 源代码,看起来它可能每次都在调用“lookup_key”(在 engine/base.py 中),而且看起来这会在本地缓存列值,我猜是懒惰地(通过 PopulateDict)。

您可以尝试通过直接使用 row.__props 绕过它(不推荐,因为它是私有的),也许您可​​以使用 row.cursor,但看起来您可以通过绕过 sqlalchemy(除了 sql 生成)并直接使用游标来获得很多.

-- Ĵ

于 2009-03-18T01:51:59.157 回答