[英]Testing Throughput of postgres database using thread pool and connection pool. But why do I only have 300 inserts per second when it should be 6000?
我想测试与PostgreSQL数据库连接的系统的吞吐量。 我的系统由2个主要组件组成:一个为newFixedThreadPool的ThreadPoolExecutor,最多具有10个线程,一个称为connectionPool的PGPoolingDataSource,其与数据库的最多10个连接。 我在postgres数据库中调用存储过程,该存储过程执行简单插入,如果插入失败,则返回错误消息。 执行一次此存储过程的调用大约需要20到30毫秒。
系统的工作方式如下:主线程创建消息任务,并将其传递给线程池。 消息任务执行以下操作:它从连接池获取连接,并在postgres服务器上调用存储过程。 它等待响应,然后任务完成。 线程池中的线程现在可以处理新的消息任务。
现在,我认为这应该可以正常工作,并且在某种程度上可以。 这只是非常缓慢,我完全不知道为什么。 使用以下代码,我每秒记录约300-500次插入,而每秒应插入6000次。 我不知道为什么。 使用系统监视器时,我看到所有cpus的负载约为20%。 当我取消注释以(1)表示的部分时,1 cpu在100%负载下,而其他cpu在0%左右,这对我来说是个谜。
如果任何人都可以就我做错的事情分享一些看法,那就太好了。 是我的postgres服务器配置不正确吗? 当我使用top命令时,它表明java使用大约20%的cpu,并且有8个postgres进程,每个大约使用3%。 (我在使用Eclipse的Ubuntu 14.04上)。
这是我的MainTester代码,其中包含main函数。 它创建线程池和数据库连接池。
public class MainTester {
public static ThreadPoolExecutor threadPoolExecutor;
public static PGPoolingDataSource connectionPool;
public static void main(String[] args) {
establishConnectionPool(10);
threadPoolExecutor = (ThreadPoolExecutor)
Executors.newFixedThreadPool(10);
Operator operator = new Operator(1, 2, 30);
operator.run();
// i created an other thread here before.
//Now I just use the main thread to run the operator
}
private static void establishConnectionPool(int nrOfConnections)
{
connectionPool = new PGPoolingDataSource();
connectionPool.setDataSourceName("ConnectionPool");
connectionPool.setServerName(dbServerName);
connectionPool.setDatabaseName(dbName);
connectionPool.setUser(dbUser);
connectionPool.setPassword(dbPassword);
connectionPool.setMaxConnections(nrOfConnections);
}
这是我的操作员代码。 它产生消息任务并将其移交给线程池。 我想让它运行2分钟,然后检查它已插入的消息量。 我想一直保持线程池的队列满,这就是为什么我检查线程池的队列是否少于1000个任务的原因。 如果数量较少,我会为线程池产生新任务。
public class Operator implements Runnable{
private int minutesToRun = 2;
private void run () {
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < minutesToRun * 60 * 1000 + 10) {
while(MainTester.threadPoolExecutor.getQueue().size() < 1000) {
MessageTask messageTask = new MessageTask(QueueOperation.SEND, 1, 1, 1, "abc");
MainTester.threadPoolExecutor.execute(messageTask);
}
try { // (1)
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(1)当我在这里不睡觉时,系统监视器显示1 cpu占100%,其他cpu占0%。 这对我来说毫无意义。 当然,此方法将完全占用一个CPU,但线程池中的线程应在另一个CPU上工作吗?
这是我的消息任务代码:
public class MessageTask implements Runnable {
private QueueOperation operation;
private int senderId;
private int receiverId;
private int queueId;
private String message;
public MessageTask (QueueOperation op, int senderId, int receiverId, int queueId, String message)
{
operation = op;
this.senderId = senderId;
this.receiverId = receiverId;
this.queueId = queueId;
this.message = message;
}
@Override
public void run() {
Connection connection = null;
try {
connection = MainTester.connectionPool.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
try{
Statement statement = connection.createStatement();
String dbStoredProcedure = "SELECT send(" + senderId + "," + receiverId + "," + queueId + "," + "'"+message+"'"+ ");";;
ResultSet resultSet = statement.executeQuery(dbStoredProcedure);
resultSet.next();
String dbResponse = resultSet.getString(1);
}
catch (SQLException e) {
}
finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
所以我的问题是:为什么它这么慢? 为什么我的全部cpus都只有20%的容量? 也许我将Postgresql服务器配置错误? 我没有更改默认配置中的任何内容。 我是否误解了线程池的工作方式? 还是连接池无法正常工作?
当测量存储的proc执行时间时,您可能没有考虑提交花费的时间。 您似乎也将注意力集中在CPU上,而完全忽略了磁盘I / O和磁盘刷新的成本。
对于具有基本SSD的典型系统而言,每秒300个事务是一个相当合理的数字。 因此,我想说您是在每次插入之后提交。
为了获得更快的结果,您需要:
commit_delay
并将synchronous_commit = off
设置synchronous_commit = off
(存在某些数据丢失风险); 要么 有关更多信息,请参见如何加快PostgreSQL中的插入性能。
如果您不介意崩溃后丢失整个数据集,也可以使用未unlogged
表。 但是,实际上,不正常关机后,您的数据将被删除。 走了 无法恢复。 因此,请确保您是认真的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.