通过Python连接到服务器上的db2数据库,并对一个巨大的表(可能200万条记录,50条cols)进行查询。这个表用于分析(OLAP可能是正确的术语),而不是用于事务。我想优化我的sql/python代码更快的查询执行。
如果对sql查询没有深入的了解,我怀疑SELECT
语句从表的第一个记录开始,一直持续到查询满足为止。FETCH FIRST 10 ROWS ONLY
在1秒内执行。然而,包括WHERE date_col > 20210701
将需要在确定前10条记录之前扫描一对100-mil记录—执行查询需要几分钟以上的时间。通过游标对象,性能是相似的。
或者,我通过Microsoft Access连接到同一个表。访问中的相同日期查询在<中执行。5秒,比我最快的SELECT
语句还快。Access肯定在幕后做了一些我不知道的事情。>
所以Access证明了这些sql查询可以快速执行。我留下了一个问题:我如何优化我的sql/python代码,以匹配Microsoft Access的性能?谢谢所有。
import ibm_db_dbi as db
import pandas as pd
cnxn = db.connect(dsn= '********',
user= '********',
password='********',
host= '********',
database='********')
cols = "{0}col1, {0}col2, {0}col3, {0}col4".format('database.')
# Executes in <1 second
fast_sql = '''SELECT {} FROM bigtable
FETCH FIRST 10 ROWS ONLY'''.format(cols)
# Executes in ~5 seconds
slower_sql = '''SELECT {} FROM bigtable
WHERE col1 = 1234
FETCH FIRST 10 ROWS ONLY'''.format(cols)
# Giving up after ~3 minutes
slowest_sql = '''SELECT {} FROM bigtable
WHERE date_col > 20210701
FETCH FIRST 10 ROWS ONLY'''.format(cols)
df = pd.read_sql_query(horribly_slow_sql , cnxn)
cnxn.close()
有几个因素影响了这个问题。
-
首要是一个简单的数据类型问题。date_col既不是整数也不是日期时间,而是CHAR格式。这会导致索引问题,从而导致查询缓慢。将结果用引号括起来:
...WHERE date_col > '20210701'
而不是...WHERE date_col > 20210701
。 -
另一个问题是对Access如何处理数据的误解。当切换到"数据表视图"时,Access不会执行整个查询。相反,它执行的操作相当于
FETCH FIRST 50 ROWS ONLY
。查询出现得如此之快,是因为服务器不需要将整个数据集发送给客户端。但是,在导出时执行整个查询。在我的例子中,这大约需要5秒,并且表示一个等同于我正在执行的Python脚本的进程。
感谢大家的评论。