0

我是 Golang 的新手,正在尝试使用 json 响应编写简单的 Web 服务器。端点之一是用于数据库访问。使用类静态响应(如任何静态字符串或简单数据转换)的平均响应时间约为 0s(<1ms)。如果我添加一些数据库请求,平均时间会增加到 250 毫秒,并且不取决于函数内容。所以我试图了解这个功能的时间。

我已经知道的:

  1. 查询数据库大约需要 40-50 毫秒
  2. 日期时间转换成本 >1ms
  3. json.Marshal成本<1ms
  4. string(json.Marshal)<1ms

我所有的问题都在rows.Next()

  1. 所有内部rows.Next()成本分别<1ms
  2. 每个row.Next()过程的成本取决于行长,大约为 10-50ms。

如果我理解db.Query()在一个请求中获取所有行并将其保存在内存中,提供虚拟游标作为迭代器(.Next())。为什么要花这么多钱?

  1. 所有row.Next()数据处理大约需要 180ms。加上40 毫秒db.Query,它大约等于总响应时间(~240 毫秒)
  2. 如果我评论所有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”。它提供了对 clickhouse 的 HTTP 接口的访问。我按预期在一个请求中获得了所有行,但是 http 请求大约需要 240 毫秒,数据处理大约需要 0 毫秒。所以我正在寻找机会保持 tcp 连接打开,以便能够在一个请求中获取所有 nessasery 行并工作使用我的程序端内存缓冲区(与 tcp/socket 缓冲区组合有一些缓冲区限制)。

更新 2。

好的,我已经尝试过原生 clickhouse 客户端(和其他类似的 DBeaver),大约 250 毫秒是这个请求的限制。但这可能只是clickhouse原生tcp接口的限制。但是什么是 40-50ms db.Query() 操作,它不返回任何行。是服务器端查询的时间吗?或者只是查询字符串检查?

4

0 回答 0