为什么多个 sql 查询 运行 是按顺序而不是同时进行的?
Why are multiple sql queries run in sequece and not concurrently?
我正在 运行ning mysql “select” 同时在单独的 go 例程中查询。然而,mysql 服务似乎收集这些查询,运行 按顺序(不是同时)然后 returns 同时收集所有结果集,并且只有在所有查询都被 运行.
我的问题是:
1.为什么这些查询运行是顺序的而不是并发的?
2. 为什么 mysql 等到所有查询都已 运行 才同时返回每个查询的结果集(即使每个结果集属于不同的 go routine 并且据说也使用单独的连接)?
另一件事:当我设置“SetMaxOpenConns(2)”时,它会同时 returns 两个结果集。如果设置为 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
查看它们是运行并行还是串行的简单技术:让每个连接都做
SELECT SLEEP(1);
如果并行,设置不会超过 1 秒。如果是连续的,那么N秒。
如果它们是运行顺序的,但是直到全部完成才输出,那就是GO问题。
如果您的 7.3s 确实是并行的而 9.5 是串行的,那么这就指出了为什么 运行 并行的东西不值得——它们会相互踩踏并且不会更快地完成。冲突可能是 CPU 或 I/O 或互斥体或网络或其他东西;这取决于查询。 (我的 sleep
测试非常 non-invasive,但需要的时间是可预测的。)
我正在 运行ning mysql “select” 同时在单独的 go 例程中查询。然而,mysql 服务似乎收集这些查询,运行 按顺序(不是同时)然后 returns 同时收集所有结果集,并且只有在所有查询都被 运行.
我的问题是:
1.为什么这些查询运行是顺序的而不是并发的?
2. 为什么 mysql 等到所有查询都已 运行 才同时返回每个查询的结果集(即使每个结果集属于不同的 go routine 并且据说也使用单独的连接)?
另一件事:当我设置“SetMaxOpenConns(2)”时,它会同时 returns 两个结果集。如果设置为 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
查看它们是运行并行还是串行的简单技术:让每个连接都做
SELECT SLEEP(1);
如果并行,设置不会超过 1 秒。如果是连续的,那么N秒。
如果它们是运行顺序的,但是直到全部完成才输出,那就是GO问题。
如果您的 7.3s 确实是并行的而 9.5 是串行的,那么这就指出了为什么 运行 并行的东西不值得——它们会相互踩踏并且不会更快地完成。冲突可能是 CPU 或 I/O 或互斥体或网络或其他东西;这取决于查询。 (我的 sleep
测试非常 non-invasive,但需要的时间是可预测的。)