Лучший способ реализовать агрегацию в Go (как GROUP BY в SQL)? - PullRequest
0 голосов
/ 29 июня 2019

Допустим, у меня есть структура

type row struct {
    f1, f2, f3 string
    v int64
}

Мы можем представить ее как строку в таблице.

Кроме того, мне нужно реализовать функцию, которая выполняет агрегирование, как этот запрос:

SELECT f1, f2, f3, SUM(v) FROM table GROUP BY f1, f2, f3

Итак, я должен реализовать функцию:

type key struct {
    f1, f2, f3 string
}
func aggregate(t []row) map[key]int64

или, если это может быть

func aggregate(t []row) map[string]row

, где ключ карты, например, f1 + f2+ f3

func aggregate(t []row)  []row

также работает, если результат будет включать уникальные комбинации f1, f2, f3 (DISTINCT f1, f2, f3)

У меня есть два варианта:

func aggregate1(t []row) map[key]int64 {
    res := map[key]int64{}
    for _, r := range t {
        res[key{r.f1, r.f2, r.f3}] += r.v
    }
    return res
}
func aggregate2(t []row) map[string]*row {
    res := map[string]*row{}
    for _, r := range t {
        var sb strings.Builder
        sb.WriteString(r.f1)
        sb.WriteString("#")
        sb.WriteString(r.f2)
        sb.WriteString("#")
        sb.WriteString(r.f3)
        id := sb.String()
        t := res[id]
        if t == nil {
            t = &row{f1: r.f1, f2: r.f2, f3: r.f3, v: 0}
            res[id] = t
        }
        t.v += r.v
    }
    return res
}

Первый вариант тратит слишком много времени на https://golang.org/pkg/runtime/?m=all#mapassign (runtime.mapassign)

Идея второго варианта заключается в использовании более быстрых https://golang.org/pkg/runtime/?m=all#mapassign_faststr (runtime.mapassign_faststr), ноstrings.Builder.WriteString устраняет все преимущества runtime.mapassign_faststr: (*

Итак, можете ли вы предложить больше идей о том, как реализовать это агрегирование?

Я думаю о том, как эффективно рассчитать "id""во втором варианте. Он должен быть уникальным. Мой вариант уникален, потому что f1, f2 и f3 не могут включать"#" персонаж.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...