2

我正在使用 jaydebeapi (Mac OS X) 来查询 Netezza 数据库并执行一些快速/肮脏的计时:

t0 = time.time()
curs.execute('''select * from table1;''')
print time.time() - t0

我自己创建了这个表,它包含 650,000 行和 9 列(整数和日期)。

当我运行上述命令时,大约需要 1.3 分钟才能完成(平均超过 10 次运行)。

然后,当我尝试获取数据时:

t0 = time.time()
curs.execute('''select * from table1;''')
row = curs.fetchone()
while row is not None:
    row = curs.fetchone()
print time.time() - t0

完成大约需要 10 分钟(平均超过 10 次运行)。

现在,当我使用 WinSQL(Windows 7,ODBC)运行相同的 SQL 查询时,返回数据大约需要 3 分钟。我似乎无法弄清楚为什么在 Python 中需要这么长时间,并且不确定如何或从哪里开始寻找。

4

3 回答 3

3

您是将 JayDeBeApi 与 JPype 结合使用还是与 Jython 结合使用?使用 JPype 实现获取大型结果集会导致对每个单元格值进行一些 JNI 调用,这会导致大量开销。您应该考虑以下选项之一:

  1. 最小化结果集的大小。使用 SQL 函数进行聚合。
  2. 试试最新的JPype1实现。有一些性能改进。
  3. 将运行时切换到 Jython(JayDeBeApi 也适用于 Jython)
  4. 直接在 Java 中实现数据库查询和数据提取,并使用 JPype 调用逻辑,但接口不返回大型数据集。
  5. 尝试改进JPypeJayDeBeApi代码
于 2014-11-30T09:44:30.300 回答
1

您可能想使用 curs.fetchmany() 而不是 fetchone。这将在某种程度上优化来回获取行。

这样的事情甚至会隐藏您一次获取多行的事实:

def fetchYield(cursor):
        li = []
        while True:
            if not li:
                li = cursor.fetchmany()
                if not li:
                    raise StopIteration
            yield li.pop(0)

for row in fetchYield(curs):
   <do something with row>

但是,我认为如果一个原始的 sql 查询工具需要 3 分钟来获取数据,那么让您的 Python 代码花费 3 倍的时间并不是完全不合理的。

于 2014-11-13T19:28:28.707 回答
1

我有一个类似的问题,我观察到使用fetchall和设置游标arraysize参数(detault 为 1)的改进,如所基于的DB-API 文档中所述JayDeBeApi

cursor = conn.cursor()
cursor.arraysize = 10000
cursor.execute("select * from table1")

rows = cursor.fetchall()

# storing data in a pandas DataFrame
df = pd.DataFrame(data=rows, columns = ["C1", "C2", "C3"])

cursor.close()

我在 600.000 行获取中观察到以下性能

arraysize = 10000 --- 509 seconds
arraysize = 1     --- 526 seconds

尽管如此,我还观察到与使用相同 JDBC 驱动程序的基于 Java 的客户端相比,获取时间要长得多。正如 9000 所说,我的建议是花一些时间在 SQL 查询上,让数据库完成工作,这是一种更快、更具可扩展性的解决方案。

于 2016-05-26T15:54:02.087 回答