duanliujie8639 2014-03-31 22:26
浏览 1443
已采纳

在Go中提高rows.Scan()的性能

I have a very simple query that returns a couple thousand rows with only two columns:

SELECT "id", "value" FROM "table" LIMIT 10000;

After issuing sql.Query(), I traverse the result set with the following code:

data := map[uint8]string{}

for rows.Next() {
    var (
        id     uint8
        value  string
    )

    if error := rows.Scan(&id, &value); error == nil {
        data[id] = value
    }
}

If I run the exact same query directly on the database, I get all results back within a couple of milliseconds, but the Go code takes far longer complete, sometimes almost 10 seconds!

I started commenting out several parts of the code and it seems that rows.Scan() is the culprit.

Scan copies the columns in the current row into the values pointed at by dest.

If an argument has type *[]byte, Scan saves in that argument a copy of the corresponding data. The copy is owned by the caller and can be modified and held indefinitely. The copy can be avoided by using an argument of type *RawBytes instead; see the documentation for RawBytes for restrictions on its use. If an argument has type *interface{}, Scan copies the value provided by the underlying driver without conversion. If the value is of type []byte, a copy is made and the caller owns the result.

Can any expect any speed improvement if I use *[]byte, *RawBytes or *interface{} instead?

Looking at the code, it looks like the convertAssign() function is doing a lot of stuff that isn't necessary for this particular query. So my question is: how can I make the Scan process faster?

I thought about overloading the function to expect predetermined types, but that isn't possible in Go...

Any ideas?

  • 写回答

1条回答 默认 最新

  • doushen2154 2014-04-01 11:35
    关注

    yes, you can use RawBytes instead and rows.Scan() will avoid memory allocation/copying

    About convertAssign() function - yes, its not optimal in Go 1.2, but they make significant improvements in 1.3:
    - http://code.google.com/p/go/issues/detail?id=7086
    - Lock-less implementation for sync.Pool

    I have some example of RawBytes usage - https://gist.github.com/yvasiyarov/9911956

    This code read data from MySQL table, make some processing and write it to CSV files. Last night it takes 1 minute 24 seconds to generate 4GB of CSV data(about 30 million rows)

    so I'm pretty sure what problem is outside of go code: even worse possible usage of rows.Scan() can not give you 10 seconds delay.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 oracle集群安装出bug
  • ¥15 关于#python#的问题:自动化测试
  • ¥20 问题请教!vue项目关于Nginx配置nonce安全策略的问题
  • ¥15 教务系统账号被盗号如何追溯设备
  • ¥20 delta降尺度方法,未来数据怎么降尺度
  • ¥15 c# 使用NPOI快速将datatable数据导入excel中指定sheet,要求快速高效
  • ¥15 再不同版本的系统上,TCP传输速度不一致
  • ¥15 高德地图2.0 版本点聚合中Marker的位置无法实时更新,如何解决呢?
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题