J'essaie d'interroger environ 10 000 lignes d'une table. Après l'avoir essayé, impliqué limit
offset
的各种其他选项并且没有找到所需的成功之后,我尝试在每个 goroutine 中查询单行。思路是每行只需要 ~5ms
来查询和获取,但是一批 10k 会接管 20s
.
Vous trouverez ci-dessous une version simplifiée du code :
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() }
Les résultats sont suivis comme suit :
{"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"}
Démarre bien et comme prévu, mais les temps de requête continuent d'augmenter.
MaxSessions
和 MinSessions
对于 spannerClient
是 100
On pourrait donc imaginer qu'il y ait un léger ralentissement après 100, mais ce n'est pas le cas.
Veuillez lire ici :
<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>
Les requêtes non itératives (ReadRow
etc.) me donnent les mêmes résultats.
L'utilisation de tx := spannerClient.Single()
en dehors d'une boucle for donnera des résultats similaires.
Question :
spannerClient.Single()
à l'intérieur de la goroutine, la goroutine essaie toujours d'utiliser la même session/transaction ? TLDR : La taille maximale par défaut du pool de sessions est de 400, ce qui signifie que vous ne pouvez jamais exécuter plus de 400 requêtes en parallèle. Vous devez augmenter la taille du pool de sessions pour obtenir cette simultanéité.
<小时/>Tout d'abord : je ne pense pas qu'envoyer 10 000 requêtes en parallèle pour que chaque requête lise une ligne ne soit pas la solution la plus efficace à votre problème. S'il n'y a pas d'autres critères que vous pouvez utiliser pour filtrer que les identifiants des employés et que ces identifiants sont dispersés partout, alors créer la requête dans le formulaire sera toujours plus efficace
select * from employees where id in unnest(@ids)
Pour un exemple complet, voir ce commentaire : https:///github.com/googleapis/google-cloud-go/issues/858#issuecomment-550982307
Retour à votre question spécifique :
it := tx.Query(gCtx, stmt2)
n'exécute it := tx.Query(gCtx, stmt2)
行确实不执行查询,它只是准备执行查询。第一次调用 row, err := it.Next()
pas row, err := it.Next()
est appelé pour la première fois. Vous pouvez également le voir dans les temps d’exécution enregistrés. La première instruction semble s'exécuter en 30 microsecondes, ce qui est impossible. Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!