Почему несколько SQL-запросов выполняются последовательно, а не одновременно? - PullRequest
1 голос
/ 23 мая 2019

Я выполняю mysql «отборные» запросы в отдельных подпрограммах go одновременно.Однако служба mysql, похоже, собирает эти запросы, запускает их последовательно (не одновременно) и затем возвращает все наборы результатов одновременно и только после того, как все запросы были выполнены.

Мои вопросы:
1. Почему эти запросы выполняются последовательно, а не одновременно?
2. Почему mysql ждет, пока все запросы не будут выполнены, прежде чем возвращать набор результатов для каждого запроса одновременно (даже если каждый отдельный набор результатов принадлежит другомуgo рутина и предположительно также использует отдельное соединение)?

Другое дело: когда я устанавливаю «SetMaxOpenConns (2)», тогда он возвращает два набора результатов одновременно.Если установлено значение 3, 3 набора результатов возвращаются одновременно.Однако они все еще всегда выполняются в последовательности.

Кто-нибудь знает, что здесь происходит?

package main

import (
    "database/sql"
    "fmt"
    "sync"
    "time"

    _ "github.com/go-sql-driver/mysql"
)

var database *sql.DB

func init() {
    var err error
    databaseURI := "root:toor@tcp(192.168.200.10:3306)/ahc"
    database, err = sql.Open("mysql", databaseURI)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println("DB Connection Established")
        //database.SetMaxIdleConns(0)
        //database.SetMaxOpenConns(2)
    }
}

func test(device string, wg *sync.WaitGroup) {
    fmt.Println("Thread: " + device + " started")
    start := time.Now()

    var count string

    //using go-sql-driver
    sqlStatement, err := database.Prepare("select count(cpeName) from report where errMessage <> \"ok\" and cpeName = ? and jobID = ?")
    if err != nil {
        fmt.Println(err)
    }
    defer sqlStatement.Close()
    err = sqlStatement.QueryRow(device, "11534").Scan(&count)
    sqlStatement.Close()


    duration := time.Since(start)
    fmt.Println("Thread: " + device + " Duration: " + duration.String() + "\n")
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    var deviceList = []string{"xx-swrk-ca-gen-s-002", "xx-leus-ca-ust-ap-068", "xx-sgvn-ca-lug-ap-004", "xx-swrk-ca-vez-s-005", "xx-swrk-ca-vez-ap-006",    "xx-leus-ca-ust-ap-065", "xx-leus-ca-ust-ap-073", "xx-leus-ca-ust-ap-076", "xx-leus-ca-ust-ap-077", "xx-swrk-ca-gen-s-001"}
    total := time.Now()
    for _, device := range deviceList {
        wg.Add(1)
        go test(device, &wg)
    }
    wg.Wait()
    duration := time.Since(total)
    fmt.Println("\n\nTotal: Duration: " + duration.String() + "\n")
}

Это вывод

DB Connection Established
Thread: xx-leus-ca-ust-ap-068 started
Thread: xx-sgvn-ca-lug-ap-004 started
Thread: xx-leus-ca-ust-ap-065 started
Thread: xx-leus-ca-ust-ap-073 started
Thread: xx-swrk-ca-vez-ap-006 started
Thread: xx-swrk-ca-vez-s-005 started
Thread: xx-leus-ca-ust-ap-076 started
Thread: xx-leus-ca-ust-ap-077 started
Thread: xx-swrk-ca-gen-s-002 started
Thread: xx-swrk-ca-gen-s-001 started
Thread: xx-leus-ca-ust-ap-076 Duration: 7.291656143s

Thread: xx-swrk-ca-gen-s-002 Duration: 7.304134404s

Thread: xx-leus-ca-ust-ap-065 Duration: 7.307958641s

Thread: xx-swrk-ca-vez-s-005 Duration: 7.313591747s

Thread: xx-leus-ca-ust-ap-077 Duration: 7.313992638s

Thread: xx-swrk-ca-vez-ap-006 Duration: 7.314905664s

Thread: xx-swrk-ca-gen-s-001 Duration: 7.320466323s

Thread: xx-leus-ca-ust-ap-073 Duration: 7.322158337s

Thread: xx-leus-ca-ust-ap-068 Duration: 7.324745097s

Thread: xx-sgvn-ca-lug-ap-004 Duration: 7.326001783s



Total: Duration: 7.326096238s

При использовании database.SetMaxOpenConns (1) это вывод:

DB Connection Established
Thread: xx-leus-ca-ust-ap-068 started
Thread: xx-swrk-ca-gen-s-001 started
Thread: xx-swrk-ca-vez-ap-006 started
Thread: xx-leus-ca-ust-ap-065 started
Thread: xx-leus-ca-ust-ap-073 started
Thread: xx-swrk-ca-gen-s-002 started
Thread: xx-leus-ca-ust-ap-077 started
Thread: xx-sgvn-ca-lug-ap-004 started
Thread: xx-leus-ca-ust-ap-076 started
Thread: xx-swrk-ca-vez-s-005 started
Thread: xx-leus-ca-ust-ap-068 Duration: 1.131790286s

Thread: xx-leus-ca-ust-ap-077 Duration: 2.128919333s

Thread: xx-swrk-ca-gen-s-001 Duration: 3.073559464s

Thread: xx-leus-ca-ust-ap-073 Duration: 4.002964333s

Thread: xx-swrk-ca-vez-s-005 Duration: 4.932256684s

Thread: xx-sgvn-ca-lug-ap-004 Duration: 5.853361245s

Thread: xx-swrk-ca-gen-s-002 Duration: 6.785042625s

Thread: xx-leus-ca-ust-ap-065 Duration: 7.705957815s

Thread: xx-swrk-ca-vez-ap-006 Duration: 8.633000734s

Thread: xx-leus-ca-ust-ap-076 Duration: 9.550948572s



Total: Duration: 9.551103129s

1 Ответ

0 голосов
/ 28 мая 2019

Простой метод, чтобы увидеть, работают ли они параллельно или последовательно: пусть каждое соединение делает

SELECT SLEEP(1);

Если параллельно, набор не займет намного больше 1 секунды.Если последовательно, то N секунд.

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

Если ваши 7.3 действительно параллельны, а 9.5 - этоЭто означает, что не стоит запускать параллельные процессы - они наступают друг на друга и не заканчиваются намного быстрее.Конфликт может быть ЦП или В / В, мьютексами, сетью или чем-то еще;это зависит от запроса.(Мой sleep тест очень неинвазивен, но занимает предсказуемое количество времени.)

...