2016-07-15 101 views
1

我正在用Go(1.6.x)sql包與PostGres(9.4)一起構建一個API。我的預備陳述是否有申請或要求範圍?閱讀完文檔後,在應用程序級對其進行縮放以減少準備階段的數量似乎更有效。但是,也許還有其他考慮因素,並且準備好的陳述並非旨在長期存在?Go sql - 準備語句範圍

回答

1

已準備好的語句可以執行重複的SQL命令,例如,這些命令可能僅在參數值上有所不同。

它們並不意味着長時間地處於「長期」狀態,因爲預先準備的語句可能(它們在事務中調用時)會保留活動的數據庫連接(「long」意味着它們不被使用時;意味着重複執行準備好的聲明多次,即使這需要很長時間)。連接是一種昂貴的資源,只能根據需要進行保存。只需創建一堆準備好的語句而不關閉它們,就可以用完主動/允許的連接,然後阻止與數據庫服務器的進一步通信。

如果您想在一個HTTP請求中多次執行與多個不同參數相同的insertupdateselect語句,請使用準備好的語句。不要使用準備好的語句來使(HTTP)請求活躍起來。

在某些驅動程序實現和數據庫服務器中,預準備語句也可能涉及分配給數據庫服務器本身(不在Go應用程序中)的資源。例如,準備好的語句可以預先編譯在數據庫服務器上,服務器可能會準備查詢執行計劃,爲其分配某些資源(如內存)。這些可能會永久保留,直到準備好的聲明關閉。

在Go中有一篇文章(由Myles McDonnell在下面的評論中發佈)進入Prepared Statements的實現細節。它提到,如果預處理語句不是從事務創建的,它們會將連接釋放回連接池,但在需要時,它們會嘗試重複使用它們準備的連接(因爲如果db服務器輔助/也扮演主動角色在準備好的語句中,它綁定到服務器端的連接)。如果沒有,他們將重新準備他們在一個新的連接(造成不良的性能開銷)。總而言之,您所描述的是一種工作模式,如果您在許多後續請求中需要/執行的準備好的語句數量較少,則可能意味着響應時間縮短。但是,這也意味着另一方面,從長遠來看,它們可能會導致所有準備好的陳述都將在所有關聯池中進行準備。決定你的情況是否可以接受。

通常應該避免這種情況(並且在HTTP請求結束之前關閉預準備語句),但是如果您只有少數幾個請求,並且您在多個請求之後確實需要它們,則可以將它們移動超出請求範圍。

+1

我的理解是,prep.stmt會將它準備回來的conn釋放回池中。然後,stmt會在執行時嘗試使用該conn,但如果conn不可用,則會再次準備新的conn(本身就是潛在的可伸縮性問題)。考慮到爲語句創建和分配資源的費用,由於我的應用程序的語句數量有限,因此在應用程序範圍內提前創建它們似乎合乎邏輯。我並不是不同意你的觀點,我可能是錯誤的,但我對此沒有足夠的理解。 –

+0

連接和預準備語句之間的WRT關係; http://go-database-sql.org/prepared.html –