MySQL Операция массовой вставки не работает должным образом - PullRequest
1 голос
/ 27 мая 2020
Обновление

. Причина, по которой я использовал код для записи на сервер MySQL с другого сервера, заключается в том, что это эксперимент. Мне нужно записать время, необходимое для завершения sh вставки всех этих строк. Загрузка данных локально в MySQL другими методами не является проблемой.

Я пытался вставить более 15 миллионов строк записей в базу данных MySQL, которая была расположена на другом сервере. Я использовал драйвер "github.com/go-sql-driver/mysql" и использовал транзакцию. Однако на вставку sh у меня уходит около 75 минут. Пропускная способность между двумя серверами превышает 1 ГБ / с. Использование ЦП и памяти MySQL составляет менее 20% за все время с 1 ядерным ЦП и 2 ГБ памяти. Фрагмент кода выглядит следующим образом:

fmt.Println("Connecting to MySQL...")

db, err := sql.Open("mysql", "root:password@tcp(ipAddress:3306)/ssc")
if err != nil {
    panic(err.Error())
}

fmt.Println("Connected to MySQL")

defer db.Close()

var transaction *sql.Tx
var stmt *sql.Stmt
transaction, err = db.Begin()
stmt, err = transaction.Prepare(`INSERT INTO Star2002PrimaryTracks(primaryTracks, offsetInByte, sizeInByte)     VALUE (?, ?, ?)`)
start := time.Now()
// primaryTracksSlice has over 10 million elements.
for i, ele := range primaryTracksSlice {
    if i != 0 && i%100000 == 0 {
        // commit transaction. init transaction and stmt
        elapsed := time.Since(start)
                    fmt.Printf("time since:%s\n", elapsed)
                    transaction.Commit()
                    fmt.Println("transaction commited with 100000 rows each.")
        elapsed = time.Since(start)
        fmt.Printf("transaction commited. time since: %s\n", elapsed)

        elapsed = time.Since(start)
        fmt.Printf("time since:%s\n", elapsed)
        transaction, err = db.Begin()
        stmt, err = transaction.Prepare(`INSERT INTO Star2002PrimaryTracks(primaryTracks, offsetInByte, sizeInByte)         VALUE (?, ?, ?)`)
        elapsed = time.Since(start)
        fmt.Printf("transaction and stmt initialization. time since: %s\n", elapsed)
    } else {
        // stmt.exec
        stmt.Exec(ele.PrimaryTracks, ele.Offset, ele.Size)
    }
}
transaction.Commit()

}

transaction.Commit (), db.Begin () и transaction.Prepare () до fini * 1026 занимает меньше секунды. *. Кажется, что 100000 stmt.Exe c () s занимает около 30 секунд для завершения sh. Я не думаю, что это займет так много времени, поскольку stmt.Exe c () не имеет ничего общего с передачей данных на сервер MySQL до тех пор, пока не будет выполнена transaction.Commit (). Я хотел бы спросить вас, ребята, что может быть не так?

Я чувствую, что мне нужно сделать обновление. Таблица создается с помощью:

CREATE TABLE `Star2002PrimaryTracks` (`id` INT UNSIGNED AUTO_INCREMENT, `primaryTracks` int, `offsetInByte` int, `sizeInByte` int, primary key (`id`))ENGINE=InnoDB DEFAULT CHARSET=utf8;

без добавления дополнительных индексов, которые могут быть причиной. Есть только первичный ключ.

Думаю, что-то не так с stmt.Exe c (). Почему выполнение занимает так много времени, если не требуется передавать данные на сервер MySQL. Не является ли transaction.Commit () единственным методом, который должен выполнять работу по передаче данных на MySQL сервер и занимает относительно много времени, чтобы завершить sh?

CREATE TABLE `Star2002PrimaryTracks` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `primaryTracks` int(11) DEFAULT NULL,
  `offsetInByte` int(11) DEFAULT NULL,
  `sizeInByte` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1067367 DEFAULT CHARSET=utf8 |
...