Небольшой пример как копировать данные между базами данных используя go, pgx, и copy.
Предположим что у нас есть два коннекта к базе (одной или нескольким, это не важно). Далее используя io.Pipe()
создаём Reader
и Writer
, и используя CopyTo()
и CopyFrom()
переносим данные.
r, w := io.Pipe()
go func() {
_, err := db1.PgConn().CopyTo(ctx, w, `copy table1 to stdout binary`)
if err != nil {
slog.Error("error", "err", err)
return
}
_ = w.Close()
}()
_, err = db2.PgConn().CopyFrom(ctx, r, `copy table1 from stdin binary`)
_ = r.Close()
Вся прелесть тут в том что используем наиболее быстрый способ с точки зрения PostgreSQL.
Используя copy (select * from where ... order by ... limit ...) to stdout
можем регулировать нагрузку на чтение, следить за прогрессом и управлять копированием данных.
В качестве Reader
может выступать что угодно, хоть файл csv, хоть другая СУБД, но тогда данные придётся дополнительно конвертировать в формат понимаемый PostgreSQL - csv или tsv, и использовать copy ... from stdin (format csv)
.
Нюанс: copy ... from stdin binary
, binary
обязывает использовать одинаковые типы данных, нельзя будет integer
колонку перенести в колонку smallint
, если такое требуется, то параметр binary
надо опустить.