【问题标题】:Postgresql + gorm complex pagination with groupsPostgresql + gorm 带组的复杂分页
【发布时间】:2021-07-04 21:58:34
【问题描述】:

我有一个带有 GroupId 列的表,并且可能有大量的行。有没有办法让这些数据按组分页?例如,获取前 10 个组,然后获取接下来的 10 个组等?

表格将具有这种结构(默认情况下不排序) - 抱歉格式错误,由于某种原因它不起作用,但我认为它是可见的

Col1 Col2 GroupId
data A foo1 1
data B foo2 1
data C foo3 2

...

那么有没有一种方法可以有效地获取前 10 组的行,然后是接下来的 10 组等,而每组的行数不固定?假设有数百万行,组可以是任意数量。

【问题讨论】:

    标签: postgresql go go-gorm


    【解决方案1】:

    它并没有真正分页,因为您只是通过有界标识符 (GroupId) 查询数据。如果您知道您的组 ID 并且它们是连续的,那么您可以执行类似的操作。这是使用纯 Go 完成的,您可以轻松地将 gorm 与此结合。

    go playground

    package main
    
    import (
        "fmt"
    )
    
    func main() {
        for _, q := range queries() {
            fmt.Println(q)
        }
    }
    
    func queries() (out []string) {
        groups := []int{10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
        for i := 0; i < len(groups); i++ {
            var lower, upper int = 0, 0
            if i != 0 {
                lower = groups[i-1]
            }
            upper = groups[i]
            q := fmt.Sprintf("SELECT * FROM MyTable WHERE GroupId >= %v AND GroupId < %v", lower, upper)
            out = append(out, q)
        }
        return
    }
    

    queries 的调用会打印出应运行的每个查询,以获取每个组中的所有结果。例如:

    SELECT * FROM MyTable WHERE GroupId >= 0 AND GroupId < 10
    SELECT * FROM MyTable WHERE GroupId >= 10 AND GroupId < 20
    SELECT * FROM MyTable WHERE GroupId >= 20 AND GroupId < 30
    SELECT * FROM MyTable WHERE GroupId >= 30 AND GroupId < 40
    SELECT * FROM MyTable WHERE GroupId >= 40 AND GroupId < 50
    SELECT * FROM MyTable WHERE GroupId >= 50 AND GroupId < 60
    SELECT * FROM MyTable WHERE GroupId >= 60 AND GroupId < 70
    SELECT * FROM MyTable WHERE GroupId >= 70 AND GroupId < 80
    SELECT * FROM MyTable WHERE GroupId >= 80 AND GroupId < 90
    SELECT * FROM MyTable WHERE GroupId >= 90 AND GroupId < 100
    

    到目前为止,我们假设您已经确切知道要查询的“组存储桶”。相反,如果我们假设我们知道有多少顺序组 (n) 以及每个查询需要多少组 (桶大小 s),我们可以轻松创建一个函数来提供我们应该查询的桶.

    go playground

    func groups(n, s int) (out []int) {
        for i := 0; i <= n; i++ {
            if i == 0 {
                continue
            }
            if i%s == 0 || i == n {
                out = append(out, i)
            }
        }
        return
    }
    

    【讨论】:

    • 谢谢!但这在海量数据的情况下是否足够高效?
    • 这不是您需要担心性能的部分。这些函数是 O(n) 时间和空间,但您的数据库将成为瓶颈,以及您决定如何处理从查询返回的内容。这些功能在我想象中几乎不会引起注意。
    • 我指的是查询部分,有没有办法以某种方式优化它?
    • @user3728390 想一想,如果您的问题需要您加载表中的每一行,那么就无法绕过加载表中的每一行。您可能可以执行一些小的优化,例如有序 SQL 索引,或者您的应用程序可以缓存不会更改的数据,或者您可以使批处理更大,从而减少花费在网络延迟开销上的时间。性能优化将归结为您如何设计应用程序。如果您必须重复加载整个表,这可能是应用程序设计不佳的标志。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    • 2021-07-05
    • 1970-01-01
    相关资源
    最近更新 更多