Python SQL查询性能

时间:2014-11-13 19:04:54

标签: python sql netezza jaydebeapi

我正在使用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中花了这么长时间,我不确定如何或从哪里开始寻找。

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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倍的时间并不是完全没有道理的。

答案 2 :(得分:1)

我遇到了类似的问题,我发现使用fetchall进行了改进,并将游标arraysize参数设置为详细信息(详细信息为1),如DB-API documentation中报告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查询上,让数据库完成工作,这是一个更快,更具可扩展性的解决方案。