doucheng4660 2015-08-30 08:39
浏览 44

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

I have this bit of code:

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)
    }
}

It is mostly just a few MySQL calls to the database to update / get a bit of information, I was wondering if anybody can tell me what I have done inefficiently here that it's causing this to take 11 seconds to run (with about 6 items to loop in the for rows.Next() call.

  • 写回答

1条回答 默认 最新

  • douyun1860 2015-08-30 08:59
    关注

    Specimen A:

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

    Specimen B: (inside for loop)

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

    Specimen C:

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

    Put profiling timing statement around these. If you don't know how, ask. Show the table schemas if you need more help by issuing show create table skinbank and show create table credits. This will enable some clue on indexes. Tell us the rowcounts of the two tables.

    If you have a ton of rows, it is possible without proper indexes that you are performing tablescans, not fast lookups, to get to the rows in the update where clause. Heck, in the select too. Right now you don't know the timings.

    At the very least, have indexes on

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

    As for specimen C, it should pick up the left-most of the composite index just suggested. So a separate index on just skinbank(tradeofferid) is overkill if you are going the composite route.

    评论

报告相同问题?

悬赏问题

  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分
  • ¥15 delphi webbrowser组件网页下拉菜单自动选择问题
  • ¥15 linux驱动,linux应用,多线程