1 回答

TA貢獻1805條經驗 獲得超10個贊
注意#1:sql.DB不代表連接,而是代表連接池。
注意#2:sql.Open初始化池,但它不必實際打開連接,只允許驗證 dsn 輸入,然后連接的打開將由池延遲處理。
你的第 db.Query一個慢的原因是因為你從一個新的連接池開始,一個有 0 個空閑(但打開)連接的連接池,因此第一個 db.Query需要首先建立與服務器的新連接,然后才會它能夠執行sql語句。
你的第二個 db.Query也很慢的原因是因為第一個創建的連接還 db.Query沒有釋放回池中,因此你的第二個 db.Query也需要先與服務器建立新的連接才能執行sql語句。
要釋放與池的連接,您需要首先保留 的主要返回值,db.Query然后調用其Close上的方法。
要從至少有一個可用連接的池開始,請Ping在初始化池后立即調用。
例子:
func main() {
// setup database connection
db, err := sql.Open("postgres", "postgres:///?sslmode=disable")
if err != nil {
panic(err)
} else if err := db.Ping(); err != nil {
panic(err)
}
for i := 0; i < 5; i++ {
// query database
firstQueryStart := time.Now()
rows, err := db.Query("select 1;")
firstQueryEnd := time.Now()
if err != nil {
panic(err)
}
// put the connection back to the pool so
// that it can be reused by next iteration
rows.Close()
fmt.Println(fmt.Sprintf("query #%d took %s", i, firstQueryEnd.Sub(firstQueryStart).String()))
}
}
我的機器上的時間(db.Ping只有 #0 很慢)
query #0 took 6.312676ms
query #1 took 102.88μs
query #2 took 66.702μs
query #3 took 64.694μs
query #4 took 208.016μs
我的機器上的時間(db.Ping#0 比沒有快很多)
query #0 took 284.846μs
query #1 took 78.349μs
query #2 took 76.518μs
query #3 took 81.733μs
query #4 took 103.862μs
關于準備好的陳述的說明:
例如,如果您正在執行一個不帶參數的簡單查詢,db.Query("select 1 where true")那么您實際上只是在執行一個簡單查詢。
但是,如果您正在執行帶有參數的查詢,例如db.Query("select 1 where $1", true),那么實際上,您正在創建和執行準備好的語句。
見4.2。值表達式,它說:
值表達式是以下之一: ...
位置參數引用,在函數定義或準備好的語句的主體中
......
位置參數也說:
位置參數引用用于指示從外部提供給 SQL 語句的值。參數用于 SQL 函數定義和準備好的查詢中。一些客戶端庫還支持獨立于 SQL 命令字符串指定數據值,在這種情況下,參數用于引用線外數據值。
postgres 的消息流協議如何指定simple queries和extended queries
擴展查詢協議將上述簡單查詢協議分解為多個步驟。準備步驟的結果可以多次重復使用以提高效率。此外, 還提供了其他功能,例如可以將數據值作為單獨的參數提供,而不必將它們直接插入到查詢字符串中。
最后,在lib/pq司機的掩護下:
...
// Check to see if we can use the "simpleQuery" interface, which is
// *much* faster than going through prepare/exec
if len(args) == 0 {
return cn.simpleQuery(query)
}
if cn.binaryParameters {
cn.sendBinaryModeQuery(query, args)
cn.readParseResponse()
cn.readBindResponse()
rows := &rows{cn: cn}
rows.rowsHeader = cn.readPortalDescribeResponse()
cn.postExecuteWorkaround()
return rows, nil
}
st := cn.prepareTo(query, "")
st.exec(args)
return &rows{
cn: cn,
rowsHeader: st.rowsHeader,
}, nil
...
- 1 回答
- 0 關注
- 202 瀏覽
添加回答
舉報