mariadb Go-SQL-Driver导致maria-db CPU利用率非常高

xdnvmnnf  于 2022-11-08  发布在  Go
关注(0)|答案(1)|浏览(137)

我有一个API,我写在python flask 的网站和应用程序的后端,它的工作很好。我最近学习了围棋,并重写了整个API在围棋。我期望更低的CPU和内存利用率从围棋二进制文件,但MariaDB现在几乎99%的利用率。
我尝试限制最大连接,最大超时,最大空闲时间,最大...等所有选项在GitHub页面仍然没有使用。我有连接作为全局变量在代码中,我在每个db.preparedb.query之后延迟result.close()。我知道Go语言比Python快得多,所以向服务器发出更多请求是有意义的,但它是唯一的测试环境,它应该会导致那么多的CPU利用率关于如何在Golang处理MariaDB建议?
FYI:原来的网站从2015年开始工作,它至少有超过百万行的数据,我可以使用gorm重新创建数据库,并再次插入数据,但我真的只想使用纯SQL(没有ORM谢谢)。

func getfulldate(c *fiber.Ctx) error {

    pid := c.FormValue("pid")

    result, err := db.Prepare("select concat(p.firstName, ' ', p.middle, ' ', p.lastName, ' ', p.forthName) as fullname,gender,bID,married,barcode,comment,address,if(p2.phone is null, 0, p2.phone)  as phone,rName,occupation,weight,height,cast(Birthdate as date) as Birthdate from profile p left join (select phID, pID, phone from phonefix group by pID) p2 on p.pID = p2.pID left join (select pID, weight, height from bmifix group by pID) B on p.pID = B.pID, religion r where r.rgID = p.rgID and p.pID = ? ")
    defer result.Close()
    if err != nil {
        return c.JSON(fiber.Map{"access_token": "wrong"})

    }

    rows, err := result.Query(pid)
    defer rows.Close()
    if err != nil {
        return c.JSON(fiber.Map{"access_token": "wrong"})

    }
    columns, err := rows.Columns()
    if err != nil {
        return err
    }
    count := len(columns)
    tableData := make([]map[string]interface{}, 0)
    values := make([]interface{}, count)
    valuePtrs := make([]interface{}, count)
    for rows.Next() {
        for i := 0; i < count; i++ {
            valuePtrs[i] = &values[i]
        }
        rows.Scan(valuePtrs...)
        entry := make(map[string]interface{})
        for i, col := range columns {
            var v interface{}
            val := values[i]
            b, ok := val.([]byte)
            if ok {
                v = string(b)
            } else {
                v = val
            }
            entry[col] = v
        }
        tableData = append(tableData, entry)
    }

    currentTime := time.Now().Format("2006-01-02")
    result, err = db.Prepare("select viID,state as done,dob from visitfix where  patientID = ?")
    defer result.Close()
    if err != nil {
        return c.JSON(fiber.Map{"access_token": "wrong"})

    }

    rows, err = result.Query(pid)
    defer rows.Close()
    if err != nil {
        return c.JSON(fiber.Map{"access_token": "wrong"})

    }
    columns = []string{"viID", "done", "dob"}

    count = len(columns)
    tableDatas := make([]map[string]interface{}, 0)
    values = make([]interface{}, count)
    valuePtrs = make([]interface{}, count)
    for rows.Next() {
        for i := 0; i < count; i++ {

            valuePtrs[i] = &values[i]
        }

        rows.Scan(valuePtrs...)

        entry := make(map[string]interface{})

        for i, col := range columns {
            var v interface{}
            val := values[i]

            b, ok := val.([]byte)

            if ok {
                v = string(b)
            } else {
                v = val
            }
            if i == 2 {
                var state string
                format := "2006-1-2"

                datea, err := time.Parse(format, string(b))
                if err != nil {
                    return err
                }
                mydate := datea.Format("2006-01-02")
                if mydate == currentTime {
                    state = "today"
                }
                if mydate < currentTime {
                    state = "older"
                }
                if mydate > currentTime {
                    state = "newer"
                }

                entry["state"] = state

            }

            entry[col] = v
        }

        tableDatas = append(tableDatas, entry)
    }
    alldata := [][]map[string]interface{}{tableData, tableDatas}
    dat, err := json.Marshal(alldata)
    if err != nil {
        return err
    }

    return c.SendString(string(dat))
}
vktxenjb

vktxenjb1#

go进程本身不应该像任何其他语言一样对(任何)数据库产生任何其他影响,除非有更好的驱动程序实现来检索行数据(MySQL的游标实现曾经(可能仍然)被破坏)。
至于游标的用法:这可以将负载分散到更长的时间,但您需要大量的数据来注意驱动程序实现和语言之间的差异。编译语言将能够在该时间点上对数据库施加更高的负载。但再次强调:这种情况很少见。
这里要查看的主要候选对象很可能是索引:您正在查询:

result, err := db.Prepare(`select concat(p.firstName, ' ', p.middle, ' ', p.lastName, ' ', p.forthName) 
as fullname,gender,bID,married,barcode,comment,address,if(p2.phone is null, 0, p2.phone)  
as phone,rName,occupation,weight,height,cast(Birthdate as date) as Birthdate 
from profile p 
left join (select phID, pID, phone from phonefix group by pID) p2 on p.pID = p2.pID 
left join (select pID, weight, height from bmifix group by pID) B on p.pID = B.pID, religion r 
where r.rgID = p.rgID and p.pID = ? `)

您希望在p.pID、r.rgID和p.rgID上有索引。那么,左连接中pID上的group by可能也会以次优方式执行(运行一个explain并检查执行计划)。
一种改进方法是删除group by语句:您没有group by函数,因此在左连接中没有group by的用处:

result, err := db.Prepare(`select concat(p.firstName, ' ', p.middle, ' ', p.lastName, ' ', p.forthName) 
as fullname,gender,bID,married,barcode,comment,address,if(p2.phone is null, 0, p2.phone)  
as phone,rName,occupation,weight,height,cast(Birthdate as date) as Birthdate 
from profile p 
left join (select phID, pID, phone from phonefix) p2 on p.pID = p2.pID 
left join (select pID, weight, height from bmifix) B on p.pID = B.pID
left join religion r 
where r.rgID = p.rgID and p.pID = ? `)

由于您总是检索单个pID,并且该pID似乎是唯一的记录,因此以下方法可能更好(无法测试:没有您的DB:)):如果可能,请转到内部联接:它的性能应该优于左连接

相关问题