データデータベース
ステートメントの時間制限
1 文に 10 秒の上限があります。超えると 57014 で打ち切られ、この値は引き上げられません。
プロジェクトのデータベースは 1 文につき 10 秒 の上限を設けます。超えるとその文が次のエラーで打ち切られます。
[57014] canceling statement due to statement timeoutなぜあるのか
プロジェクトのデータベースはワーカーと同じプロセス内で 単一レーン で実行されます。1 文が長く走ると、そのプロジェクトへの他のリクエストがすべて後ろで待ちます。上限はその待ち時間を 10 秒に抑えます。
show statement_timeout は 0 です
この上限は PostgreSQL の statement_timeout 設定ではなく、ランタイムが別に持つ天井です。そのため SHOW statement_timeout は 0 を返し、SET statement_timeout で引き上げることはできません。引き下げは可能です — セッションに短い statement_timeout を置けばそちらが先に効きます。
エラーコードが同じ 57014 なので、コードでは区別できません。10 秒付近で切れたなら、この天井です。
当たったら
文を分割してください。大きな UPDATE はキー範囲で区切って複数回実行し、大量の INSERT は 1,000 行前後に区切って セッション 1 つのトランザクションに入れます。
// 12,000 件の best_rank 再計算 — 1 文だと 10 秒を超える
for (let offset = 0; ; offset += 2000) {
const ids = await env.db.exec("select id from places order by id limit 2000 offset $1", [offset]);
if (ids.length === 0) break;
await env.db.exec(
`update places p set best_rank = b.min_rank
from (select place_id, min(rank) as min_rank from rankings
where place_id = any($1) group by place_id) b
where b.place_id = p.id`,
[ids.map((r) => r.id)],
);
}空のテーブルで通ったマイグレーションが、データが入った後に同じ文で引っかかることがあります。相関サブクエリの UPDATE が典型です — 集約を一度行ってから結合すれば、たいてい上限内に収まります。
値
| 項目 | 値 |
|---|---|
| 1 文の上限 | 10 秒 |
| SQLSTATE | 57014 |
| 引き上げ | 不可 |
| 引き下げ | 可 (SET statement_timeout) |