簡體   English   中英

使用線程池和連接池測試postgres數據庫的吞吐量。 但是為什么我每秒只有300次插入,而應該是6000次呢?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM