亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

golang中配置?sql.DB獲得更好的性能

 更新時間:2023年10月27日 11:05:41   作者:北漂燕郊楊哥  
這篇文章主要介紹了golang中如何配置?sql.DB獲得更好的性能,在這篇文章中,我想準(zhǔn)確解釋這些設(shè)置的作用,并展示它們可能產(chǎn)生的(積極和消極)影響,需要的朋友可以參考下

有很多很好的教程討論 Go 的sql.DB類型以及如何使用它來執(zhí)行 SQL 數(shù)據(jù)庫查詢和語句。但它們中的大多數(shù)都掩蓋了SetMaxOpenConns()、SetMaxIdleConns()和SetConnMaxLifetime()方法——您可以使用它們來配置 的行為sql.DB并改變其性能。

在這篇文章中,我想準(zhǔn)確解釋這些設(shè)置的作用,并展示它們可能產(chǎn)生的(積極和消極)影響。

打開和空閑連接
我將從一些背景開始。

對象sql.DB是許多數(shù)據(jù)庫連接的池,其中包含“使用中”和“空閑”連接。當(dāng)您使用連接執(zhí)行數(shù)據(jù)庫任務(wù)(例如執(zhí)行 SQL 語句或查詢行)時,連接將被標(biāo)記為正在使用。任務(wù)完成后,連接將標(biāo)記為空閑。

當(dāng)您指示sql.DB執(zhí)行數(shù)據(jù)庫任務(wù)時,它將首先檢查池中是否有任何空閑連接可用。如果有一個可用,那么 Go 將重用此現(xiàn)有連接,并將其標(biāo)記為在任務(wù)期間正在使用。如果當(dāng)你需要一個連接時池中沒有空閑連接,那么 Go 將創(chuàng)建一個額外的新附加連接。

SetMaxOpenConns 方法

默認(rèn)情況下,同時打開的連接數(shù)(使用中+空閑)沒有限制。SetMaxOpenConns()但你可以通過這樣的方法實現(xiàn)你自己的限制:

// Initialise a new connection pool
db, err := sql.Open("postgres", "postgres://user:pass@localhost/db")
if err != nil {
    log.Fatal(err)
}
// Set the maximum number of concurrently open connections (in-use + idle)
// to 5. Setting this to less than or equal to 0 will mean there is no 
// maximum limit (which is also the default setting).
db.SetMaxOpenConns(5)

在此示例代碼中,池現(xiàn)在最大限制為 5 個并發(fā)打開的連接。如果所有 5 個連接都已標(biāo)記為正在使用,并且需要另一個新連接,則應(yīng)用程序?qū)⒈黄鹊却钡?5 個連接之一被釋放并變?yōu)榭臻e。

為了說明更改的影響,MaxOpenConns我運行了基準(zhǔn)測試,將最大打開連接設(shè)置為 1、2、5、10 和無限制。該基準(zhǔn)測試在 PostgreSQL 數(shù)據(jù)庫上執(zhí)行并行語句,您可以在這個要點INSERT中找到代碼。結(jié)果如下:

BenchmarkMaxOpenConns1-8                 500       3129633 ns/op         478 B/op         10 allocs/op
BenchmarkMaxOpenConns2-8                1000       2181641 ns/op         470 B/op         10 allocs/op
BenchmarkMaxOpenConns5-8                2000        859654 ns/op         493 B/op         10 allocs/op
BenchmarkMaxOpenConns10-8               2000        545394 ns/op         510 B/op         10 allocs/op
BenchmarkMaxOpenConnsUnlimited-8        2000        531030 ns/op         479 B/op          9 allocs/op
PASS

編輯:要明確的是,此基準(zhǔn)測試的目的不是模擬應(yīng)用程序的“現(xiàn)實生活”行為。它只是為了幫助說明sql.DB幕后的行為方式以及更改MaxOpenConns對該行為的影響。

INSERT對于此基準(zhǔn)測試,我們可以看到允許的打開連接越多,在數(shù)據(jù)庫上執(zhí)行操作所需的時間就越少(1 個打開連接的 3129633 ns/op 與無限制連接的 531030 ns/op 相比,大約快 6 倍)。這是因為允許的打開連接越多,可以并發(fā)執(zhí)行的數(shù)據(jù)庫查詢就越多。

SetMaxIdleConns 方法

默認(rèn)情況下,sql.DB連接池中最多保留2個空閑連接。您可以通過SetMaxIdleConns()如下方法更改此設(shè)置:

// Initialise a new connection pool
db, err := sql.Open("postgres", "postgres://user:pass@localhost/db")
if err != nil {
    log.Fatal(err)
}
// Set the maximum number of concurrently idle connections to 5. Setting this
// to less than or equal to 0 will mean that no idle connections are retained.
db.SetMaxIdleConns(5)

從理論上講,允許池中存在更多數(shù)量的空閑連接將提高性能,因為它使得需要從頭開始建立新連接的可能性降低,從而有助于節(jié)省資源。

讓我們看一下相同的基準(zhǔn)測試,最大空閑連接數(shù)設(shè)置為none、1、2、5和10(并且打開的連接數(shù)不受限制):

BenchmarkMaxIdleConnsNone-8          300       4567245 ns/op       58174 B/op        625 allocs/op
BenchmarkMaxIdleConns1-8            2000        568765 ns/op        2596 B/op         32 allocs/op
BenchmarkMaxIdleConns2-8            2000        529359 ns/op         596 B/op         11 allocs/op
BenchmarkMaxIdleConns5-8            2000        506207 ns/op         451 B/op          9 allocs/op
BenchmarkMaxIdleConns10-8           2000        501639 ns/op         450 B/op          9 allocs/op
PASS

當(dāng)MaxIdleConns設(shè)置為 none 時,必須為每個連接從頭開始創(chuàng)建一個新連接,INSERT從基準(zhǔn)測試中我們可以看到平均運行時間和內(nèi)存使用量相對較高。

僅允許保留和重用 1 個空閑連接,這對這個特定的基準(zhǔn)測試產(chǎn)生了巨大的影響——它使平均運行時間減少了約 8 倍,內(nèi)存使用量減少了約 20 倍。繼續(xù)增加空閑連接池的大小可以使性能變得更好,盡管改進(jìn)不太明顯。

那么你應(yīng)該維護(hù)一個大的空閑連接池嗎?答案是這取決于應(yīng)用程序。

重要的是要認(rèn)識到,保持空閑連接處于活動狀態(tài)是有代價的 - 它會占用本來可用于應(yīng)用程序和數(shù)據(jù)庫的內(nèi)存。

如果連接空閑時間太長,它也可能變得不可用。例如,MySQL 的wait_timeout設(shè)置將自動關(guān)閉 8 小時內(nèi)未使用的所有連接(默認(rèn)情況下)。

當(dāng)這種情況發(fā)生時,sql.DB優(yōu)雅地處理它。壞連接在放棄之前會自動重試兩次,此時 Go 將從池中刪除該連接并創(chuàng)建一個新連接。因此,設(shè)置得MaxIdleConns太高實際上可能會導(dǎo)致連接變得不可用,并且比擁有較小的空閑連接池(使用更頻繁的連接更少)時使用更多的資源。因此,實際上,如果您可能很快會再次使用連接,那么您實際上只想保持連接空閑。

最后要指出的一件事是MaxIdleConns應(yīng)該始終小于或等于MaxOpenConns。Go 會強制執(zhí)行此操作,并在必要時自動減少MaxIdleConns。

SetConnMaxLifetime 方法

現(xiàn)在讓我們看一下SetConnMaxLifetime()設(shè)置連接可以重用的最大時間長度的方法。如果您的 SQL 數(shù)據(jù)庫還實現(xiàn)了最長連接生存期,或者例如您希望在負(fù)載均衡器后面輕松地交換數(shù)據(jù)庫,那么這會很有用。

你像這樣使用它:

// Initialise a new connection pool
db, err := sql.Open("postgres", "postgres://user:pass@localhost/db")
if err != nil {
    log.Fatal(err)
}
// Set the maximum lifetime of a connection to 1 hour. Setting it to 0
// means that there is no maximum lifetime and the connection is reused
// forever (which is the default behavior).
db.SetConnMaxLifetime(time.Hour)

在此示例中,我們的所有連接將在首次創(chuàng)建 1 小時后“過期”,并且過期后無法重復(fù)使用。但請注意:

這并不能保證連接將在池中存在整整一個小時;連接很可能由于某種原因變得不可用并在此之前自動關(guān)閉。
連接在創(chuàng)建后仍然可以使用一小時以上 - 只是在那之后無法開始重用。
這不是空閑超時。連接將在首次創(chuàng)建后 1 小時到期,而不是在最后一次空閑后 1 小時。
每秒自動運行一次清理操作,以從池中刪除“過期”連接。
從理論上講,連接越短,ConnMaxLifetime連接過期的頻率就越高,因此,需要從頭開始創(chuàng)建連接的頻率就越高。

ConnMaxLifetime為了說明這一點,我運行了設(shè)置為 100ms、200ms、500ms、1000ms 和無限制(永久重復(fù)使用)的基準(zhǔn)測試,默認(rèn)設(shè)置為無限制打開連接和 2 個空閑連接。這些時間段顯然比您在大多數(shù)應(yīng)用程序中使用的時間段短得多,但它們有助于很好地說明行為。

BenchmarkConnMaxLifetime100-8               2000        637902 ns/op        2770 B/op         34 allocs/op
BenchmarkConnMaxLifetime200-8               2000        576053 ns/op        1612 B/op         21 allocs/op
BenchmarkConnMaxLifetime500-8               2000        558297 ns/op         913 B/op         14 allocs/op
BenchmarkConnMaxLifetime1000-8              2000        543601 ns/op         740 B/op         12 allocs/op
BenchmarkConnMaxLifetimeUnlimited-8         3000        532789 ns/op         412 B/op          9 allocs/op
PASS

在這些特定的基準(zhǔn)測試中,我們可以看到,與無限生命周期相比,100 毫秒生命周期的內(nèi)存使用量增加了 3 倍多,并且每個生命周期的平均運行時間也INSERT稍長。

如果您ConnMaxLifetime在代碼中進(jìn)行了設(shè)置,請務(wù)必記住連接過期(并隨后重新創(chuàng)建)的頻率。例如,如果您總共有 100 個連接,連接時間ConnMaxLifetime為 1 分鐘,那么您的應(yīng)用程序每秒可能會終止并重新創(chuàng)建多達(dá) 1.67 個連接(平均)。您不希望這個頻率太高,以至于最終會阻礙性能,而不是幫助它。

超出連接限制

最后,如果不提及超過數(shù)據(jù)庫連接數(shù)量的硬限制會發(fā)生什么,那么本文就不完整。

作為說明,我將更改我的postgresql.conf文件,因此總共只允許 5 個連接(默認(rèn)值為 100)…

max_connections = 5

然后以無限的開放連接重新運行基準(zhǔn)測試…

BenchmarkMaxOpenConnsUnlimited-8    --- FAIL: BenchmarkMaxOpenConnsUnlimited-8
    main_test.go:14: pq: sorry, too many clients already
    main_test.go:14: pq: sorry, too many clients already
    main_test.go:14: pq: sorry, too many clients already
FAIL

一旦達(dá)到 5 個連接的硬限制,我的數(shù)據(jù)庫驅(qū)動程序 ( pq ) 就會立即返回一條sorry, too many clients already錯誤消息,而不是完成INSERT.

為了防止出現(xiàn)此錯誤,我們需要將打開連接的最大總數(shù)(使用中 + 空閑)設(shè)置sql.DB為低于 5。如下所示:

// Initialise a new connection pool
db, err := sql.Open("postgres", "postgres://user:pass@localhost/db")
if err != nil {
    log.Fatal(err)
}
// Set the number of open connections (in-use + idle) to a maximum total of 3.
db.SetMaxOpenConns(3)

sql.DB現(xiàn)在,任何時刻最多只能創(chuàng)建 3 個連接,并且基準(zhǔn)測試運行時應(yīng)該不會出現(xiàn)任何錯誤。

但這樣做有一個很大的警告:當(dāng)達(dá)到打開連接限制并且所有連接都在使用中時,應(yīng)用程序需要執(zhí)行的任何新數(shù)據(jù)庫任務(wù)都將被迫等待,直到連接空閑并標(biāo)記為空閑。例如,在 Web 應(yīng)用程序的上下文中,用戶的 HTTP 請求可能會“掛起”,甚至可能在等待數(shù)據(jù)庫任務(wù)運行時超時。

為了緩解這種情況,您應(yīng)該在進(jìn)行數(shù)據(jù)庫調(diào)用時始終傳遞一個context.Context具有固定、快速、超時的對象,使用啟用上下文的方法,例如ExecContext(). 可以在此處的要點中看到一個示例。

總之

根據(jù)經(jīng)驗,您應(yīng)該明確設(shè)置一個MaxOpenConns值。這應(yīng)該大大低于數(shù)據(jù)庫和基礎(chǔ)設(shè)施對連接數(shù)量的硬性限制。
一般來說,MaxOpenConns和MaxIdleConns值越高,性能越好。但回報是遞減的,您應(yīng)該意識到,擁有太大的空閑連接池(連接未被重用并最終變壞)實際上會導(dǎo)致性能下降。
為了減輕上述第 2 點的風(fēng)險,您可能需要設(shè)置相對較短的ConnMaxLifetime. 但您不希望這個時間太短,導(dǎo)致連接被頻繁地不必要地終止和重新創(chuàng)建。
MaxIdleConns應(yīng)始終小于或等于MaxOpenConns。
對于中小型 Web 應(yīng)用程序,我通常使用以下設(shè)置作為起點,然后根據(jù)實際吞吐量水平的負(fù)載測試結(jié)果進(jìn)行優(yōu)化。

db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5*time.Minute)

到此這篇關(guān)于golang中配置 sql.DB獲得更好的性能的文章就介紹到這了,更多相關(guān)golang配置 sql.DB內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關(guān)文章

  • Golang?websocket協(xié)議使用淺析

    Golang?websocket協(xié)議使用淺析

    這篇文章主要介紹了Golang?websocket協(xié)議的使用,WebSocket是一種新型的網(wǎng)絡(luò)通信協(xié)議,可以在Web應(yīng)用程序中實現(xiàn)雙向通信,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • Golang如何讀取單行超長的文本詳解

    Golang如何讀取單行超長的文本詳解

    這篇文章主要給大家介紹了關(guān)于Golang如何讀取單行超長文本的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2021-12-12
  • go語言實現(xiàn)抓取高清圖片

    go語言實現(xiàn)抓取高清圖片

    本文給大家分享的是使用go語言實現(xiàn)的抓取高清美女圖片的代碼,原理非常簡單,這里就不多廢話了,主要是看到很多小伙伴使用python實現(xiàn)的,心血來潮就用go寫了下,推薦給大家。
    2015-03-03
  • 瞅一眼就能學(xué)會的GO并發(fā)編程使用教程

    瞅一眼就能學(xué)會的GO并發(fā)編程使用教程

    隨著互聯(lián)網(wǎng)的普及,互聯(lián)網(wǎng)用戶人數(shù)原來越多,這對系統(tǒng)的性能帶來了巨大的挑戰(zhàn)。這個時候就需要并發(fā)編程了,本文為大家整理了詳細(xì)的GO并發(fā)編程使用教程,讓你看完就能學(xué)會
    2023-02-02
  • 安裝Sublime?Text支持Go插件的方法步驟

    安裝Sublime?Text支持Go插件的方法步驟

    本文主要介紹了安裝Sublime?Text支持Go插件的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Go獲取與設(shè)置環(huán)境變量的方法詳解

    Go獲取與設(shè)置環(huán)境變量的方法詳解

    go環(huán)境變量的配置其實說真的說難也難,說不難也不難,只要配置成功過一次以后后面都很簡單,但是最好是要做好筆記,這篇文章主要給大家介紹了關(guān)于Go獲取與設(shè)置環(huán)境變量的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 詳解Golang中Channel的用法

    詳解Golang中Channel的用法

    如果說goroutine是Go語言程序的并發(fā)體的話,那么channels則是它們之間的通信機制。這篇文章主要介紹Golang中Channel的用法,需要的朋友可以參考下
    2020-11-11
  • 淺談Go語言中的結(jié)構(gòu)體struct & 接口Interface & 反射

    淺談Go語言中的結(jié)構(gòu)體struct & 接口Interface & 反射

    下面小編就為大家?guī)硪黄獪\談Go語言中的結(jié)構(gòu)體struct & 接口Interface & 反射。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 深度剖析Golang如何實現(xiàn)GC掃描對象

    深度剖析Golang如何實現(xiàn)GC掃描對象

    這篇文章主要為大家詳細(xì)介紹了Golang是如何實現(xiàn)GC掃描對象的,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價值,需要的小伙伴可以參考一下
    2023-03-03
  • golang?waitgroup的具體使用

    golang?waitgroup的具體使用

    本文主要介紹了golang?waitgroup的具體使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07

最新評論