java - Prepared 语句的 executeQuery() 方法的执行时间与相应的存储过程执行时间

标签 java postgresql stored-procedures prepared-statement

我有一些中间件 java 代码在服务器机器上运行,它调用远程机器上 Postgresql 数据库 (9.1) 中的存储过程 insertMessageOne

PreparedStatement sendOne = con.prepareStatement(
            "SELECT insertMessageOne(?, ?, ?, ?, ?, ?)");

// Following is the call to Stored procedure through PreparedStatement sendOne
long start = System.nanoTime();
ResultSet rs = sendOne.executeQuery();
long end = System.nanoTime();
long elapsed = (end - start)/1000000;
fileLog.write(System.currentTimeMillis() + ": " + "sendOne.executeQuery(): " + elapsed + "\n");

从日志中可以看出executeQuery耗时几十毫秒。

1385732177920: sendOne.executeQuery(): 13 
1385732178331: sendOne.executeQuery(): 20
1385732178436: sendOne.executeQuery(): 23

但是,对于存储过程 insertMessageOne(代码如下):

CREATE OR REPLACE FUNCTION insertMessageOne(sender_id INT, receiver_id INT, queue_id INT, context INT, priority INT, text varchar(2000))
RETURNS BOOLEAN 
AS $$
DECLARE
    start timestamp;
    stop timestamp;
BEGIN
    start = clock_timestamp();
    INSERT INTO message(sender_id, receiver_id, queue_id, context, priority, text) VALUES($1,$2,$3,$4,$5,$6);
    stop = clock_timestamp();
    RAISE NOTICE 'Timestamp: (%) senderId: (%) insertMessageOne: (%)', stop, sender_id, stop - start;
    RETURN TRUE;
EXCEPTION
    WHEN OTHERS THEN
        RAISE NOTICE 'EXCEPTION: INSERT SINGLE-Q MESSAGE FAILED';
        RETURN FALSE;
END;
$$ LANGUAGE plpgsql;

在日志中看到的存储过程的执行时间非常短(不到 1-2 毫秒):

NOTICE:  Timestamp: (2013-11-29 15:29:06.012125) senderId: (49) insertMessageOne: (00:00:00.000684)                                                    
NOTICE:  Timestamp: (2013-11-29 15:29:06.012848) senderId: (16) insertMessageOne: (00:00:00.000702)                                                    
NOTICE:  Timestamp: (2013-11-29 15:29:06.013465) senderId: (10) insertMessageOne: (00:00:00.000617) 

为什么executeQuery的执行时间比Stored procedure的相应执行时间要大?在这种情况下,网络延迟/带宽应该不是问题,因为代码是在集群中的机器上运行的(彼此直接连接)。我需要考虑一些步骤(在 executeQuery() 调用和存储过程 insertMessageOne() 的实际执行之间)吗?

最佳答案

从函数内部测量的 INSERT 持续时间不包括提交,因为 postgres 从不在函数内部隐式提交(或者甚至是显式提交,如果您尝试,COMMIT 语句会在函数内部引发错误)。

如果 JDBC 连接处于自动提交模式,这意味着从服务器的角度来看,客户端没有发出 SQL BEGIN 开始事务,那么 postgres 将为自己创建一个“查询期间的内部”事务,并在查询结束时提交。

10-20 毫秒是在普通磁盘上提交所需时间的典型值,因此它似乎可以解释您所看到的时差。

如果您将一系列 INSERT 分组在单个事务中,则此延迟应该低得多(如评论中所讨论的那样,仍然存在网络开销)

关于java - Prepared 语句的 executeQuery() 方法的执行时间与相应的存储过程执行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20307375/

相关文章:

java - 无法加载放置在 mac 资源中的 chrome 可执行文件(在 windows 中运行良好)

java - J2Objc 类型项目的设计模式

java - 如何设置点击按钮的点击限制?点击限制等于分数超过5

java - 如何通过 Mockito 模拟无法访问的第三方类属性

arrays - 如何为 N 列做与 array_to_json(array_agg(tags.*)) 完全相同的事情

mongodb - postgresql 或 Mongodb 用于存储位置数据(纬度和经度)并基于以下内容进行搜索?

ruby-on-rails - 为 json 列设置默认值

C# 带参数的存储过程

sql-server - 使用存储过程进行计算

c# - ORA-08103 程序错误