Pull to refresh

Небольшой пример как копировать данные между базами данных используя 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 надо опустить.

Весь код туть. И ещё немного кода для вдохновения.

Tags:
Rating0
Comments0

Articles