与 Oracle 相比,提高 postgreql 插入性能。 Postgresql 线程的内存利用率低

Posted

技术标签:

【中文标题】与 Oracle 相比,提高 postgreql 插入性能。 Postgresql 线程的内存利用率低【英文标题】:Improve postgreql insert performance when compared to Oracle. Low memory utilization by Postgresql threads 【发布时间】:2015-10-18 03:07:40 【问题描述】:

我正在尝试提高 Postgresql(版本 9.2.3)插入的性能,该表具有 1 个 bigint、1 个 varchar、1 个浮点和 2 个时间戳

附上我的 JDBC 程序的简单复制。以下是我想提的重点:

    我在托管 PostgreSQL 数据库的同一系统上运行此程序。 (64 GB RAM 和 8 个 CPU。) 我正在使用 INSERT 语句并且我不想使用 COPY 语句。我已阅读并理解 COPY 的性能更好,但我正在这里调整插入性能。 我正在使用 PreparedStatement.addbatch() 和 executeBatch() 批量插入 1000 个

当我增加批量大小时插入的性能可以很好地扩展,但在批量大小约为 8000 时会变平。我注意到系统上的 postgresql 线程 CPU 饱和,正如“top”命令所观察到的那样。当批处理大小达到 8K 时,postgres 线程的 CPU 使用率稳步增加并达到 95%。我注意到的另一件有趣的事情是每个线程最多只使用 200MB 的 RAM。

相比之下,Oracle DB 的可扩展性要好得多,并且相同数量的 insets 具有相当的批处理大小,完成速度要快 3 到 4 倍。我登录到 Oracle DB 机器(Sun Solaris 机器)并注意到 CPU 利用率在更大的批处理大小时达到峰值,并且每个 Oracle 线程正在使用 6 到 8 GB 的内存。

鉴于我有可用内存,有没有办法增加 postgres 线程的内存使用量以获得更好的性能?

这是我当前的 postgresql 设置:

temp_buffers = 256MB                    

bgwriter_delay = 100ms
bgwriter_lru_maxpages = 1000
bgwriter_lru_multiplier = 4
maintenance_work_mem = 2GB              
shared_buffers = 8GB                    
vacuum_cost_limit = 800
work_mem = 2GB
max_connections = 100

checkpoint_completion_target = 0.9
checkpoint_segments = 32
checkpoint_timeout =10min
checkpoint_warning =1min

wal_buffers = 32MB
wal_level = archive


cpu_tuple_cost = 0.03
effective_cache_size = 48GB
random_page_cost = 2

autovacuum = on
autovacuum_vacuum_cost_delay = 10ms
autovacuum_max_workers = 6
autovacuum_naptime = 5
autovacuum_vacuum_threshold = 100
autovacuum_analyze_threshold = 100
autovacuum_vacuum_scale_factor = 0.2
autovacuum_analyze_scale_factor = 0.1
autovacuum_vacuum_cost_limit = -1

以下是测量结果:

是时候在 postgreql 中插入 200 万行了。 批处理大小 - 执行批处理时间(秒) 1K - 73 2K - 64 4K - 60 8K - 59 10K - 59 20K - 59 40K - 59

是时候在 Oracle 中插入 400 万行了。 批处理大小 - 执行批处理时间(秒) 1K - 14 2K - 12 4K - 10 8K - 8.9 10K - 8.4

如您所见,Oracle 插入 400 万行表的速度比 Postgresql 快得多。

这是我用于插入的程序的 sn-p。

stmt.executeUpdate("CREATE TABLE "
                + tableName
                + " (P_PARTKEY bigint not null, "
                + " P_NAME varchar(55) not null, "
                + " P_RETAILPRICE float not null, "
                + " P_TIMESTAMP Timestamp not null, "
                + " P_TS2 Timestamp not null)");

PreparedStatement pstmt = conn.prepareStatement("INSERT INTO " + tableName + " VALUES (?, ?, ?, ?, ? )");

        for (int i = start; i <= end; i++) 
            pstmt.setInt(1, i);
            pstmt.setString(2, "Magic Maker " + i);
            pstmt.setFloat(3, i);
            pstmt.setTimestamp(4, new Timestamp(1273017600000L));
            pstmt.setTimestamp(5, new Timestamp(1273017600000L));

            pstmt.addBatch();
            if (i % batchSize == 0) 
                pstmt.executeBatch();
            
        

【问题讨论】:

转帖:dba.stackexchange.com/questions/108242/… 只是一个简单的建议:您是否使用另一种语言进行过相同的测试? Oracle 和 PostgreSQL 之间的差异可能至少部分是由于所使用的 JDBC 驱动程序的差异。 【参考方案1】:

autovacuum_analyze_scale_factor = 0.002 autovacuum_vacuum_scale_factor = 0.001

您可能需要更改上述参数

在决定是否触发 ANALYZE 时,指定要添加到 autovacuum_analyze_threshold 的表大小的一部分。默认值为 0.1(表大小的 10%)。在我们的例子中,我们将其降低到 0.002 以使其更具侵略性。

在决定是否触发 VACUUM 时,指定要添加到 autovacuum_vacuum_threshold 的表大小的一部分。默认值为 0.2(表大小的 20%)。

【讨论】:

以上是关于与 Oracle 相比,提高 postgreql 插入性能。 Postgresql 线程的内存利用率低的主要内容,如果未能解决你的问题,请参考以下文章

在执行 postgreql 函数时提交事务

与 SSE2 相比,为啥 AVX 没有进一步提高性能?

与同步类相比,使用非同步类的性能如何提高? [复制]

与mysql相比neo4j性能(如何提高?)

如何提高 Android Webkit 中的图像质量(与 iOS 相比)

与 CPython 相比,Numba 和 Cython 并没有显着提高性能,也许我使用不正确?