# #postgresql #go #go-gorm
Вопрос:
У меня есть таблица со столбцом groupId и потенциально огромным количеством строк. Есть ли способ упорядочить эти данные по группам? Например, получить первые 10 групп, затем следующие 10 групп и т. Д.?
Таблица имела бы такую структуру (не отсортированную по умолчанию) — извините за плохое форматирование, по какой-то причине это не сработало, но я думаю, что это видно
Col1 | Col2 | ГруппИд |
---|---|---|
данные A | фу1 | 1 |
данные B | фу2 | 1 |
данные C | фу3 | 2 |
…
Итак, есть ли способ эффективно получать строки из первых 10 групп, затем следующих 10 групп и т.д. С не фиксированным количеством строк в группе? Допустим, существуют миллионы строк, и групп может быть любое число.
Ответ №1:
На самом деле он не разбит на страницы так сильно, как если бы вы просто запрашивали данные с помощью ограниченного идентификатора ( GroupId
). Если вы знаете идентификаторы своих групп и они являются последовательными, то вы могли бы сделать что-то вроде этого. Это делается с помощью pure Go, вы можете легко подключить к этому gorm.
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
), мы можем легко создать функцию, которая предоставит нам группы, к которым мы должны выполнить запрос.
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
}
Комментарии:
1. Спасибо! но достаточно ли это эффективно в случае огромного объема данных?
2. Это не та пьеса, о которой вам нужно беспокоиться из-за производительности. Эти функции являются O(n) временем и пространством, но ваша база данных будет узким местом, а также тем, как вы решите обрабатывать то, что возвращается из запросов. Я бы предположил, что эти функции будут практически незаметны.
3. Я имел в виду часть запроса, есть ли способ как-то оптимизировать это?
4. @user3728390 подумайте об этом, если ваша проблема требует, чтобы вы загружали каждую строку в таблице, то нет никакого способа обойти загрузку каждой строки в таблице. Могут быть некоторые незначительные оптимизации, которые вы можете выполнить, например, упорядоченные индексы SQL, или ваше приложение может кэшировать данные, которые не меняются, или вы можете увеличить пакеты, чтобы сократить время, затрачиваемое на задержки в сети. Оптимизация производительности будет зависеть от того, как вы разрабатываете свое приложение. Если вам придется загружать всю таблицу несколько раз, это может быть признаком плохого дизайна приложения.