N 1問題対策 - HirokiYoshida837/ISUCON2022 GitHub Wiki

N+1問題対策

1. INNER JOINで一括取得できないか

Inner Joinで一撃で取得。 取得する用の構造体を作らないといけない場合もある。

2. 1+1にできないか (別クエリによるプリロード)

for文内での1つずつのデータ取得を、IN句やNamedExec、sqlx.Inを使ってリストとして取れないかを検討する。

sqlx.Inを使うサンプル

query,param, err := sqlx.In(
  "SELECT * FROM `users` WHERE `id` IN (?)",
  ids,
)
// named query with a struct
p := Place{Country: "South Africa"}
rows, err := db.NamedQuery(`SELECT * FROM place WHERE country=:country`, p)
 
// named query with a map
m := map[string]interface{}{"city": "Johannesburg"}
result, err := db.NamedExec(`SELECT * FROM place WHERE city=:city`, m)

3. キャッシュからの参照にできないか

N回のクエリを発行する対象をインメモリキャッシュやmemcached、redisなどに入れておいて、 DBではなくキャッシュに対してN回、取得リクエストを実行する。