2014-10-01 68 views
3

我有這樣一段代碼:+的NodeJS PostgreSQL的方式太慢

var pg = require('pg'); 
var QueryStream = require('pg-query-stream'); 
var constr = 'postgres://devel:[email protected]/tcc'; 
var JSONStream = require('JSONStream'); 
var http = require('http'); 

pg.connect(constr, function(err, client, done) { 
    if (err) { 
     console.log('Erro ao conectar cliente.', err); 
     process.exit(1); 
    } 

    sql = 'SELECT \ 
      pessoa.cod, \ 
      pessoa.nome, \ 
      pessoa.nasc, \ 
      cidade.nome AS cidade \ 
      FROM pessoa, cidade \ 
      WHERE cidade.cod IN (1, 2, 3);'; 

    http.createServer(function (req, resp) { 
     resp.writeHead(200, { 'Content-Type': 'text/html; Charset=UTF-8' }); 
     var query = new QueryStream(sql); 
     var stream = client.query(query); 

     //stream.on('data', console.log); 
     stream.on('end', function() { 
      //done(); 
      resp.end() 
     }); 
     stream.pipe(JSONStream.stringify()).pipe(resp); 
    }).listen(8080, 'localhost'); 
}); 

當我在它上面運行Apache的替補席,它獲得每秒大約只有四項要求。 如果我在php/apache或java/tomcat中運行相同的查詢,我會得到十倍於 的結果。該數據庫有1000行。如果我將查詢限制爲大約十行,則 那麼節點比php/java快兩倍。

我在做什麼錯?

編輯:前一段時間我在這裏開了一個問題:https://github.com/brianc/node-postgres/issues/653

,因爲我張貼那裏我已經嘗試了一些代碼,其他的變化,我提供這個鏈接。 即使有評論和提示到目前爲止,我還沒有能夠獲得下降的速度。

+3

您的所有客戶端是否與數據庫共享相同的連接?如果是這種情況,您的請求可能會被序列化。我不確定此代碼是否正確使用連接池。 – Brandon 2014-10-01 01:57:33

+0

@Brandon,是的,他們是。我也試過[這個來自node-postgres文檔的例子](https://github.com/brianc/node-postgres/wiki/Example),但結果大致相同。 – 2014-10-01 11:38:15

+1

@FernandoBasso,首先,我沒有真正使用任何類型的sql數據庫,但是從我讀到的有關querystream的內容來看,它只保留內存中的少量行。所以我認爲瓶頸是querystream,你可以嘗試沒有查詢流 – 2014-11-08 21:41:39

回答

0

看起來像您正在等待服務器在請求被中繼之前創建。嘗試在呼叫之外移動http.createServer。如果您只想在請求中使用http服務器,則應該嘗試將呼叫設置爲異步。

+0

nodejs是異步iirc,同樣,將http.createServer移動到'pg.connect'之外會導致它使用從'pg.connect'獲取的變量名'client' – 2014-11-08 21:36:53

+0

@freeforalltousez默認情況下它是異步的,但是調用內部的代碼需要使用異步包。截至目前代碼讀取1)連接到pg,2)查詢,3)創建服務器,管道流。 – 2014-11-08 23:42:31

+0

在這裏我想代碼讀取1)連接到PG,2)創建服務器和端口,3)查詢客戶端(瀏覽器)連接到服務器時,管道流 – 2014-11-09 00:02:03

0

也許你應該設置http.agent.maxSockets值,試試這個:

var http = require('http'); 
http.agent.maxSockets = {{number}}; 

默認maxSockets是5

4
  • pg-query-stream使用遊標。
  • 它使用遊標(粗體)。
  • 您可以閱讀代碼並更改batchSize以更好地滿足您的需求。

對於那些誰也不知道是什麼光標,總之他們是一個折衷保持內存佔用小,內存不讀整個表。但是,如果您獲得100行,那麼當您有1000結果時,那就是1000/100往返行程;所以可能10x比不使用遊標的解決方案慢。

如果您知道需要多少行,請在查詢中添加limit,然後更改每次返回的行數以最小化往返行程數。

+1

downvoted因爲沒有必要無禮 – 2017-06-12 15:35:39

+0

@giladmayani,你說這部分答案是粗魯的?你能否詳細說明哪些部分?我會修好它。 – dnozay 2017-06-12 17:47:28

+1

我發現你重複的部分「它使用**遊標**」2額外的時間是粗魯的,聽起來諷刺。 – 2017-06-13 14:30:02

0

據我所知,從這段代碼可以看出,你創建了一個連接到PostgreSQL的單一連接,並且所有東西都通過它排隊。

pg模塊允許這一點,它的描述如下: https://github.com/brianc/node-postgres/wiki/Queryqueue

如果你想有一個真正的表現,對於每個HTTP請求,你應該獲取從池中的連接,使用它,釋放它,使101 %確定你總是釋放(例如正確的異常處理),否則一旦池完全耗盡,你的服務器就會死亡。

一旦你在那裏,你可以調整連接池參數並測量性能。