Попытайтесь улучшить скорость вставки с MySQL - PullRequest
0 голосов
/ 22 ноября 2018

Привет, мне нужно загрузить огромное количество мелкой текстовой информации в MySQL.К сожалению, в MySQL нет BulkOp, поэтому я пытаюсь использовать go-рутины для распараллеливания транзакций.Проблема в том, что все эти параллельные и гоночные вещи сводят меня с ума.

И я не уверен, хорошо ли то, к чему я прихожу.

Упрощенный код выглядит следующим образом: огромный файл сканируется построчно, и строки добавляются к срезу, когда размер среза равен 1000

sem := make(chan int, 10) //Transactions pool
sem2 := make(chan int) // auxiliary blocking semaphore
for scanner.Scan() {
  line := scanner.Text()
  lines = append(lines, line)
  if len(lines) > 1000 {
     sem <- 1 //keep max 10 transactions
      go func(mylines ...lineT) {
        // I  use variadic, to avoid issue with pointers
        // I want to path data by values. 
        <-sem2 // all lines of slice copied, release the lock
        gopher(mylines...) //gopher does the transaction by iterating
                           //every each line. And here I may use slice
                           //I think.

        <-sem  //after transaction done, release the lock
       }(lines...)
       sem2 <- 1 //this to ensure, that slice will be reset, 
                 //after values are copied to func, otherwise 
                 //lines could be nil before the goroutine fired.
       lines = nil //reset slice
   }
}

Как лучше решить проблему,Я знаю, что мог бы сделать что-то для массового импорта через утилиты MySQL, но это невозможно.Я также не могу сделать это как INSERT со многими значениями VALUES ("1", "2), ("3", "4"), потому что он не экранирует должным образом, и я просто получаю ошибки.

Так выглядит странно, но не как мой первый подход

func gopher2(lines []lineT) {
  q := "INSERT INTO main_data(text) VALUES "
  var aur []string
  var inter []interface{}
  for _, l := range lines {
    aur = append(aur, "(?)")
    inter = append(inter, l)
  }
  q = q + strings.Join(aur, ", ")

   if _, err := db.Exec(q, inter...); err != nil {
     log.Println(err)
   }

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