Rumah >pembangunan bahagian belakang >Golang >Mengapa pertanyaan Spanner menggunakan ReadOnlyTransaction dalam golang goroutine secara beransur-ansur menjadi lebih perlahan?
Saya cuba menanyakan kira-kira 10,000 baris daripada jadual. Selepas mencuba terlibat limit
offset
的各种其他选项并且没有找到所需的成功之后,我尝试在每个 goroutine 中查询单行。思路是每行只需要 ~5ms
来查询和获取,但是一批 10k 会接管 20s
.
Ditunjukkan di bawah ialah versi ringkas kod:
func queryEmp(IDs[]string, spannerClient *spanner.Client) (Employee,error){ query := "Select name from Employee Where id = @id" g, gCtx := errgroup.WithContext(ctx) for _, ID := range IDs { id := ID g.Go(func() error { tx := spannerClient.Single() defer tx.Close() stmt2 := spanner.NewStatement(query) stmt2.Params = map[string]interface{}{ "ID": id, } qstart := time.Now() it := tx.Query(gCtx, stmt2) defer it.Stop() logrus.Debugf("%s took %v \n", "query execution.", time.Since(qstart)) for { row, err := it.Next() if err == iterator.Done { break } if err != nil { return err } var eID string if err := row.Column(0, &eID); err != nil { return err } } return nil }) } err = g.Wait() }
Keputusan dikesan seperti berikut:
{"message":"query execution. took 39.677µs \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 34.125µs \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 26.634µs \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 29.303µs \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} ... ... ... {"message":"query execution. took 188.749562ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 276.424692ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 188.62849ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 217.067524ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 276.949166ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} ... ... ... {"message":"query execution. took 454.64281ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 452.0848ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 525.748738ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 454.704656ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} {"message":"query execution. took 455.4276ms \n","severity":"debug","time":"2023-11-03T20:51:29-04:00"} ... ... ... {"message":"query execution. took 6.767574136s \n","severity":"debug","time":"2023-11-03T20:52:00-04:00"} {"message":"query execution. took 6.780578444s \n","severity":"debug","time":"2023-11-03T20:52:00-04:00"} {"message":"query execution. took 6.785085491s \n","severity":"debug","time":"2023-11-03T20:52:00-04:00"} {"message":"query execution. took 6.779527006s \n","severity":"debug","time":"2023-11-03T20:52:00-04:00"}
Bermula dengan baik dan seperti yang dijangkakan, tetapi masa pertanyaan terus meningkat.
MaxSessions
和 MinSessions
对于 spannerClient
是 100
Jadi seseorang akan membayangkan ia mungkin melihat sedikit kelembapan selepas 100, tetapi itu tidak berlaku.
Sila baca di sini:
<code> Sessions can execute only one transaction at a time. Standalone reads, writes, and queries use a transaction internally, and count toward the one transaction limit. </code>
Pertanyaan tidak berulang (ReadRow
dll) memberi saya hasil yang sama.
Menggunakan tx := spannerClient.Single()
di luar gelung for akan memberikan hasil yang serupa.
Soalan:
spannerClient.Single()
di dalam goroutine, goroutine masih cuba menggunakan sesi/transaksi yang sama? TLDR: Saiz kumpulan sesi maksimum lalai ialah 400, bermakna anda tidak boleh menjalankan lebih daripada 400 pertanyaan secara selari. Anda perlu meningkatkan saiz kumpulan sesi untuk mencapai keselarasan ini.
Pertama sekali: Saya tidak fikir menghantar 10,000 pertanyaan secara selari supaya setiap pertanyaan membaca satu baris bukanlah penyelesaian yang paling berkesan untuk masalah anda. Jika tiada apa-apa lagi yang boleh anda lakukan untuk menapis mengikut ID pekerja, dan ID tersebut tersebar di merata tempat, ia akan menjadi lebih cekap untuk membuat pertanyaan dalam bentuk
select * from employees where id in unnest(@ids)
Untuk contoh lengkap, lihat ulasan ini: https:///github.com/googleapis/google-cloud-go/issues/858#issuecomment-550982307
Kembali kepada soalan khusus anda:
it := tx.Query(gCtx, stmt2)
it := tx.Query(gCtx, stmt2)
行确实不执行查询,它只是准备执行查询。第一次调用 row, err := it.Next()
tidak row, err := it.Next()
dipanggil buat kali pertama. Anda juga boleh melihat ini dalam masa pelaksanaan yang direkodkan. Pernyataan pertama nampaknya dilaksanakan dalam masa 30 mikrosaat, yang mustahil. Atas ialah kandungan terperinci Mengapa pertanyaan Spanner menggunakan ReadOnlyTransaction dalam golang goroutine secara beransur-ansur menjadi lebih perlahan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!