我是Golang的新手,正在尝试编写带有json响应的简单网络服务器。端点之一是用于数据库访问。对于类似静态的响应(例如任何静态字符串或简单的数据转换),平均响应时间约为0s(<1ms)。如果添加一些数据库请求,则平均时间最多增加250ms,而不取决于函数内容。因此,我试图了解此功能的时间。
我已经知道的:
json.Marshal
花费<1毫秒string(json.Marshal)
<1ms 我所有的问题都出在rows.Next()
:
rows.Next()
内部的所有内容分别花费<1毫秒row.Next()
过程的开销取决于行的长度,大约为10-50ms。 如果我理解db.Query()
在一个请求中获取所有行并将其保留在内存中,以提供虚拟游标作为迭代器(.Next()
)。为什么要花这么多钱?
row.Next()
数据处理大约需要180毫秒。 db.Query
等于40毫秒,大约等于总响应时间(〜240毫秒)row.Next()
个周期进行注释,仅使db.Query
的总响应时间仍在200-240毫秒之间,则我使用的包裹:
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"os"
"strconv"
"time"
"github.com/kshvakov/clickhouse"
routing "github.com/qiangxue/fasthttp-routing"
"github.com/valyala/fasthttp"
)
func getRecs(client string, dt string) string {
dtT := transformDate(&dt)
rows, err := db.Query(getRecsRequest(&client, &dtT))
if err != nil {
log.Fatal(err)
}
defer rows.Close()
start := time.Now()
got := []databaseRows{}
elapsed := time.Since(start)
for rows.Next() {
elapsed = time.Since(start)
log.Printf("Next took %s", elapsed)
var r databaseRows
err := rows.Scan(&r.ItemIds, &r.DtRecommendation, &r.Number)
if err != nil {
log.Fatal(err)
}
got = append(got, r)
start = time.Now()
}
jsonData, err := json.Marshal(&got)
return string(jsonData)
}
func getRecs(client string, dt string) string {
dtT := transformDate(&dt)
rows, err := db.Query(getRecsRequest(&client, &dtT))
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// start := time.Now()
got := "[]databaseRows{}"
// elapsed := time.Since(start)
// for rows.Next() {
// elapsed = time.Since(start)
// log.Printf("Next took %s", elapsed)
// var r databaseRows
// err := rows.Scan(&r.ItemIds, &r.DtRecommendation, &r.Number)
// if err != nil {
// log.Fatal(err)
// }
// got = append(got, r)
// start = time.Now()
// }
jsonData, err := json.Marshal(&got)
return string(jsonData)
}
我可以期望Web服务器的响应时间大约是数据库请求时间吗?
更新。
我用“ github.com/kshvakov/clickhouse”尝试了“ github.com/jmoiron/sqlx”,结果是一样的。仅语法已更改。
我还尝试了“ github.com/mailru/go-clickhouse”和“ database / sql”。它提供对HTTPhouse Clickhouse的访问。我按预期将所有行放在一个记录中,但是http请求花费了大约240ms的时间,数据处理花费了大约0ms的时间。因此,我正在寻找保持tcp连接打开的机会,以便能够在一个请求中获取所有nessasery行并进行工作与我的程序端内存缓冲区(与tcp / socket缓冲区结合使用时有一些缓冲区限制)。
更新2。
好吧,我已经尝试了本机Clickhouse客户端(以及其他此类DBeaver),大约250ms是此请求的限制。但这可能仅仅是Clickhouse本机tcp接口的限制。 但是40-50ms的db.Query()操作是什么,它不返回任何行。是在服务器端查询时间了吗?还是只是查询字符串检查?