sql - 如何让 rows.Scan 更有效率?
问题描述
我有一个用 Go 编写的 Web 应用程序,这个应用程序对 Postgres 数据库进行查询。当我取回我的记录时,我正在使用 rows.Next 遍历记录,并使用 rows.Scan 将每一行扫描到一个结构。
我怎样才能使整个过程更快?
我认为这个程序效率不高,因为随着数据库的每条新记录,扫描所有记录的时间也会增加。我考虑过使用 goroutine,但我担心可能两个 goroutine 会扫描相同的数据。我可以通过使用互斥锁来防止这种情况吗?但是,如果我们通过使用互斥锁来阻止其他 goroutine 访问数据,那么使用并发有什么意义呢?
这是我计划改进的代码:
func GetUsers() ([]publicUser, error) {
query := `select user_id, first_name, last_name, registered_at from users;`
rows, err := db.Query(query)
if err != nil {
return nil, err
}
var us []publicUser
for rows.Next() {
var u publicUser
if err = rows.Scan(&u.UserId, &u.FirstName, &u.LastName, &u.RegisteredAt); err != nil {
log.Println(err, "GetUsers")
return nil, err
}
us = append(us, u)
}
if err := rows.Err(); err != nil {
log.Println(err, "GetUsers2")
return nil, err
}
return us, nil
}
我应该像这样启动一个新的 goroutine 吗?
func GetUsers() ([]publicUser, error) {
query := `select user_id, first_name, last_name, registered_at from users;`
rows, err := db.Query(query)
if err != nil {
return nil, err
}
var us []publicUser
for rows.Next() {
go func() {
var u publicUser
if err = rows.Scan(&u.UserId, &u.FirstName, &u.LastName, &u.RegisteredAt); err != nil
{
log.Println(err, "GetUsers")
return nil, err
}
us = append(us, u)
}()
}
if err := rows.Err(); err != nil {
log.Println(err, "GetUsers2")
return nil, err
}
return us, nil
}
解决方案
人们通常通过使用分页来解决这个问题。基本思想是客户端一次可以请求n
多条记录,并且每个后续请求都返回n
偏移量n
*的记录i + 1
(i
您当前正在进行的循环迭代在哪里)。
例如,如果您通过前端 GUI 显示此用户列表,您可能希望有一个表一次显示 50 个结果,而不是整个数据库中的所有用户,因为这会减慢您的前端速度。每当用户点击查看下一页时,您将向服务器发出一个新请求,请求 50 个结果,偏移 50(因为我们现在请求第 2 页)。这种方法解决了这种情况下的真正瓶颈,即您的数据库,而不是您的服务器代码。有关更多信息,请参阅此资源。
可列出的集合应该支持分页,即使结果通常很小。
另请参阅此 SO 答案以获取对 SQL 查询结果进行分页的示例。
推荐阅读
- python - 自底向上构建二叉树
- python - Django - 如何创建一个有效的 slug url?
- python - Python 2.7 csv 模块仅 498 项
- react-native - 在 React Native 中使用状态和道具
- ruby-on-rails - Pundit::NotAuthorizedError - ApplicationPolicy 继承不起作用
- python - 从python中的文本拆分
- reactjs - 连接 Redux devtools 和 Thunk 中间件到 store
- javascript - 仅向网络爬虫提供静态预渲染版本的 create-react-app 应用程序
- java - 缺少返回语句 java 编译错误与内部方法异常
- ios - Swift In App Subscription 如何检查活动状态?