[英]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.