我正在尝试优化一些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将结果作为元组列表或列表列表而不是字典列表返回?或者,任何人都可以建议任何其他优化吗?
答案 0 :(得分:2)
原谅显而易见的答案,但为什么查询中没有row.x == row.y?例如:
mytable.select().where(mytable.c.x==mytable.c.y)
应该给你带来巨大的性能提升。 Read the rest of the documentation.
答案 1 :(得分:1)
我认为row.items()
正是您所寻找的。它返回行的(键,值)元组列表。
答案 2 :(得分:1)
SQLAlchemy代理对底层数据库游标的所有访问,以将命名键映射到行元组中的位置,并执行任何必要的类型转换。底层实现经过了大量优化,几乎可以缓存所有内容。查看反汇编,进一步优化的唯一方法似乎是抛弃可扩展性并摆脱一些属性查找或者求助于动态代码生成以获得更小的增益,或者为了获得更多,实现相应的ResultProxy和RowProxy类下进行。
一些快速分析显示我的笔记本电脑上每次查询的开销约为5us。如果只对数据进行简单的处理,那将是很重要的。在这种情况下,下降到dbapi级别可能是合理的。这并不意味着您必须丢失SQLAlchemy的查询构建功能。只需像往常一样执行语句,并通过访问ResultProxy
从result.cursor.cursor
获取dbapi游标。 (result.cursor
是一个SQLAlchemy CursorFairy对象)然后你可以使用常规的dbapi fetchall(),fetchone()和fetchmany()方法。
但是如果你真的在进行简单的处理,那么它可能是有用的,或者至少是数据库服务器上的过滤部分。您可能会丢失数据库可移植性,但这可能不是问题。
答案 3 :(得分:0)
您应该发布您的探查器结果以及围绕'_get_col'调用的堆栈跟踪,以便我们知道正在调用哪个_get_col。 (以及_get_col是否确实是瓶颈)。
我查看了sqlalchemy源代码,看起来每次都可以调用'lookup_key'(在engine / base.py中),它看起来像是在本地缓存列值,我猜是懒惰(通过PopulateDict)。
您可以尝试通过直接使用行.__道具(不推荐,因为它是私有的)绕过它,也许你可以row.cursor,但看起来你可以通过绕过sqlalchemy(除了sql生成)和直接工作获得很多/一个光标。
- J