Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database Postgres:使用游标更新时的惊人性能_Database_Postgresql_Database Performance - Fatal编程技术网

Database Postgres:使用游标更新时的惊人性能

Database Postgres:使用游标更新时的惊人性能,database,postgresql,database-performance,Database,Postgresql,Database Performance,考虑下面的两个Python代码示例,它们实现了相同的效果,但却有着显著而令人惊讶的性能差异 import psycopg2, time conn = psycopg2.connect("dbname=mydatabase user=postgres") cur = conn.cursor('cursor_unique_name') cur2 = conn.cursor() startTime = time.clock() cur.execute("SELECT * FROM test f

考虑下面的两个Python代码示例,它们实现了相同的效果,但却有着显著而令人惊讶的性能差异

import psycopg2, time

conn = psycopg2.connect("dbname=mydatabase user=postgres")
cur = conn.cursor('cursor_unique_name')  
cur2 = conn.cursor()

startTime = time.clock()
cur.execute("SELECT * FROM test for update;")
print ("Finished: SELECT * FROM test for update;: " + str(time.clock() - startTime));
for i in range (100000):
    cur.fetchone()
    cur2.execute("update test set num = num + 1 where current of cursor_unique_name;")
print ("Finished: update starting commit: " + str(time.clock() - startTime));
conn.commit()
print ("Finished: update : " + str(time.clock() - startTime));

cur2.close()
conn.close()
以及:

表测试的create语句为:

CREATE TABLE test (id serial PRIMARY KEY, num integer, data varchar);
该表包含100000行和真空分析测试;已经运行了

在几次尝试中,我始终得到以下结果

第一个代码示例:

Finished: SELECT * FROM test for update;: 0.00609304950429
Finished: update starting commit: 37.3272754429
Finished: update : 37.4449708474
Finished: update starting commit: 24.574401185
Finished committing: 24.7331461431
第二个代码示例:

Finished: SELECT * FROM test for update;: 0.00609304950429
Finished: update starting commit: 37.3272754429
Finished: update : 37.4449708474
Finished: update starting commit: 24.574401185
Finished committing: 24.7331461431

这让我非常惊讶,因为我认为应该正好相反,这意味着根据答案,使用游标的更新应该要快得多。

我不认为测试是平衡的-您的第一个代码是从游标获取数据,然后更新,而第二种方法是在不获取数据的情况下,盲目地按ID更新。我假设第一个代码序列转换为一个FETCH命令,然后是UPDATE-因此这是两个客户机/服务器命令转换,而不是一个

(第一段代码也是从锁定表中的每一行开始的——这会将整个表拉入缓冲区缓存——尽管考虑到这一点,我怀疑这实际上会影响性能,但您没有提到)

另外,我认为对于一个简单的表,通过ctid更新(我假设是当前的……如何工作)和通过主键更新之间不会有太大区别-pkey更新是一个额外的索引查找,但除非索引很大,否则不会有太大的降级

对于像这样更新100000行,我怀疑大部分时间都是用来生成额外的元组并将它们插入或追加到表中,而不是定位前一个元组以将其标记为已删除