【发布时间】:2017-12-31 14:58:51
【问题描述】:
我使用 PostgreSQL 9.6,我的表模式如下:department, key, value1, value2, value3, ... 每个部门都有数亿个唯一键,但所有部门的键集或多或少都相同。某些部门的某些密钥可能不存在,但这种情况很少见。
我想为两个部门准备一份报告,指出每个键值的差异(比较涉及一些仅基于键值的逻辑)。
我的第一个方法是在 python 中编写一个外部工具:
- 为查询创建服务器端游标:
SELECT * FROM my_table WHERE department = 'ABC' ORDER BY key; - 为查询创建另一个服务器端游标:
SELECT * FROM my_table WHERE department = 'XYZ' ORDER BY key; - 遍历两个游标,并比较值。
它工作得很好,但我认为在 PostgreSQL 的存储过程中执行比较会更有效。我写了一个存储过程,它接受两个游标作为参数,遍历它们并比较值。任何差异都会写入临时表。最后,外部工具只遍历临时表——那里不应该有很多行。
我认为后一种方法会更有效,因为它不需要在数据库之外传输大量数据。 令我惊讶的是,它竟然慢了近 40%。
为了隔离问题,我比较了在存储过程和 python 中迭代游标的性能:
FETCH cur_1 INTO row_1;
WHILE (row_1 IS NOT NULL) LOOP
rows = rows + 1;
FETCH FROM cur_1 INTO row_1;
END LOOP;
对比
conn = psycopg2.connect(PG_URI)
cur = conn.cursor('test')
cur.execute(query)
cnt = 0
for row in cur:
cnt += 1
查询在这两种情况下都是相同的。同样,外部工具速度更快。
我的假设是,这是因为存储过程一个接一个地获取行(FETCH FROM curs_1 INTO row_1),而应用程序分批获取 2000 行。但我找不到从游标中获取一批行的方法PgSQL 过程。因此,我无法检验假设。
所以我的问题是可以加快我的存储过程吗?
解决此类问题的最佳方法是什么?
【问题讨论】:
-
缺少一些关键元素以获得最佳答案:精确的表定义(
CREATE TABLE显示数据类型和约束的语句)。有关数据分布的更多信息:每个(department, key)有多少行:min、avg、max。现有索引。point out differences用简单的英语听起来不错,但没有定义比较和结果的确切要求。更具体。
标签: database postgresql stored-procedures cursor plpgsql