为什么这一小段代码需要11秒才能执行这几个数据库调用?

时间:2015-08-30 08:39:15

标签: mysql go

我有这段代码:

package tradebot

import (
    "log"
    "net/http"
    "strconv"

    "github.com/Philipp15b/go-steam/tradeoffer"
    "github.com/gorilla/mux"
)

func AcceptTrade(w http.ResponseWriter, r *http.Request) {

    vars := mux.Vars(r)
    var tradeId tradeoffer.TradeOfferId
    var sTradeId string
    if _, has := vars["TradeId"]; has {
        var err error
        sTradeId = vars["TradeId"]
        id, err := strconv.ParseUint(vars["TradeId"], 10, 64)
        if err != nil {
            http.Error(w, "Error accepting trade offer", 500)
        }
        tradeId = tradeoffer.TradeOfferId(id)
    }

    err := Trader.Accept(tradeId)
    if err != nil {
        log.Println(err.Error())
        http.Error(w, "Failed to accept trade try again after", 500)
    }
    rows, err := Db.Query("SELECT DepositedBy, Price FROM skinbank WHERE tradeofferid=? AND accepted=?", sTradeId, 0)
    if err != nil {
        log.Println(err)
        http.Error(w, "Your trade offer was accepted but there was an error on our side. Please open a ticket with the trade ID: "+sTradeId+" so we can address this issue. Thank you and sorry for the inconvenience", 500)
    }
    foundRows := false
    for rows.Next() {
        foundRows = true
        var price float64
        var depositedby string
        err = rows.Scan(&depositedby, &price)
        if err != nil {
            log.Println(err)
            http.Error(w, "Your trade offer was accepted but there was an error on our side. Please open a ticket with the trade ID: "+sTradeId+" so we can address this issue. Thank you and sorry for the inconvenience", 500)
        }
        if err != nil {
            log.Println(err)
            http.Error(w, "Your trade offer was accepted but there was an error on our side. Please open a ticket with the trade ID: "+sTradeId+" so we can address this issue. Thank you and sorry for the inconvenience", 500)
        }
        log.Println(depositedby, price)
        _, err := Db.Query("UPDATE accounts SET credits = credits + ? WHERE steamid=?", price, depositedby)
        if err != nil {
            log.Println(err)
            http.Error(w, "Your trade offer was accepted but there was an error on our side. Please open a ticket with the trade ID: "+sTradeId+" so we can address this issue. Thank you and sorry for the inconvenience", 500)
        }
    }

    _, err = Db.Query("UPDATE skinbank SET accepted=? WHERE tradeofferid=?", 1, sTradeId)
    if err != nil {
        log.Println(err)
        http.Error(w, "Your trade offer was accepted but there was an error on our side. Please open a ticket with the trade ID: "+sTradeId+" so we can address this issue. Thank you and sorry for the inconvenience", 500)
    }
    log.Println("Trade accepted: " + sTradeId)
    if foundRows {
        http.Redirect(w, r, "/profile", 303)
    } else {
        http.Error(w, "No trade with that id, either doesn't exist or already accepted.", 500)
    }
}

这主要只是对数据库的一些MySQL调用来更新/获取一些信息,我想知道是否有人可以告诉我我在这里效率低下的事情,这导致这需要11秒才能运行(大约在for rows.Next()来电中循环播放6个项目。

1 个答案:

答案 0 :(得分:2)

标本A:

rows, err := Db.Query("SELECT DepositedBy, Price FROM skinbank 
WHERE tradeofferid=? AND accepted=?", sTradeId, 0)

标本B :(内部循环)

_, err := Db.Query("UPDATE accounts SET credits = credits + ? WHERE steamid=?", price, depositedby)

标本C:

_, err = Db.Query("UPDATE skinbank SET accepted=? WHERE tradeofferid=?", 1, sTradeId)

围绕这些进行分析时序陈述。如果你不知道如何,请问。如果您需要更多帮助,请发布show create table skinbankshow create table credits,以显示表架构。这将为索引提供一些线索。告诉我们两个表的行数。

如果您有大量行,则可能没有正确的索引,您正在执行tablecans而不是快速查找,以获取update where子句中的行。哎呀,在选择中也是如此。现在你还不知道时间。

至少要有索引

skinbank(tradeofferid,accepted) -- a composite index, useful for Specimen A
credits(steamid) -- useful for Specimen B

对于标本C,它应该选择刚刚建议的最左侧的复合指数。因此,如果你要使用复合路线,那么仅仅皮肤库(tradeofferid)的单独索引就是过度的。