EmDash 1.3 で coalesce: true を足すと D1 の読み取りが 1.2 並みに戻る
Astro 製の CMS「EmDash」の 1.3 が出ました。1.2.0 の EmDash は公開ページを表示するたびに、レイアウトが使いそうなサイト設定やメニュー、ウィジェット、タグとカテゴリの一覧を、ページ自身のクエリと並行して先に読み込んでいました(以下、先読み)。私はこの先読みが全タグとカテゴリを毎回読むのを嫌い、EmDash 本体に手元でパッチを当ててタグとカテゴリの先読みだけを止めていました。1.3 では、先読みが走るかどうかが、astro.config.mjs で D1 をつなぐ d1() に渡す設定で分かれます。session は D1 のセッション(クエリを順に流す仕組み)を使う設定、coalesce は同時に出たクエリを batch にまとめて送る設定です。既定では先読みが走り、session: "auto" だけにすると止まり、新しいテンプレートのように coalesce: true も付けると走ります。

そこで、1.3 に上げると D1 の読み取りがどう変わるのか、coalesce: true を足すとどうなるのかを確かめてみました。
D1 を session: "auto" で使うサイトでは先読みが止まり、トップページを表示したときの読み取りは手元の計測で 439行から 18行に減って、パッチは要らなくなりました。一方で coalesce: true を足すと先読みが戻り、往復は 3回から 2回に減りましたが、読み取りは 1.2.0 とほぼ同じ 440行に戻りました。
1.3 では session: "auto" のサイトの先読みが止まる
1.3.0 では、session を "auto" か "primary-first" にしたサイトは、サイト設定やメニューなどを、ページが実際に使ったときにだけ読みます。リリースの記事は、先読みがページ自身の最初のクエリを待たせていたことを理由に挙げています。
先読みを走らせるかどうかは、ミドルウェアの次の判定で決まります(middleware.ts の 998〜1003行目)。
if (
acceptsHtml &&
anonScoped.db.getExecutor().adapter.supportsMultipleConnections !== false
) {
after(() => prefetchLayoutData());
}ログインしていない人の HTML のリクエストで、アダプタが同時に複数のクエリを受け付けると答えたときだけ先読みを走らせています。coalesce 無しのセッションのアダプタは supportsMultipleConnections に false を返すので、先読みは走りません。d1() に session を書いていないサイトでは、1.3.0 でもアダプタが同時に複数のクエリを受け付けると答えるので、先読みは走ります。
どれだけ減るのかを、同じサイトを astro build して astro preview で動かし、ローカルの workerd と D1 で測りました。DB にはタグ 202件とカテゴリ 2件を入れ、ログインしていない状態でトップページを 1回表示したときに D1 が返す rows_read とクエリの数を数えています。
- 1.2.0: 6本のクエリで 439行
- 1.2.0 に、私がタグとカテゴリの先読みを止めるパッチを当てた版: 4本のクエリで 30行
- 1.3.0(パッチ無し): 3本のクエリで 18行

1.2.0 で増えていた分の大半は、タグの一覧を読むクエリで、これだけで 404行を読んでいました。1.3.0 ではタグとカテゴリを読むクエリが無く、メニューとウィジェットの先読みのクエリも消えています。行数はタグとカテゴリの数で変わり、本番で同じ行数になるとは限りません。
coalesce: true で先読みが戻る
coalesce はまだ実験的な機能です。リリースの記事は、coalesce: true のサイトは先読みを続け、それを 1回の往復にまとめるとしています。
同じ DB で 1.3.0 に coalesce: true を足すと、トップページ 1回の表示で 7本のクエリが 440行を読み、往復は 2回でした。最初の batch はメニューの一覧、ウィジェットエリア、カテゴリの一覧、タグの一覧、ページ自身の記事の 5本で、次の batch はメニューの項目を読むクエリなど 2本です。メニューの項目は最初の batch で読んだメニューの一覧を受けて読むので、次の batch に回っています。往復が 3回から 2回に減ることで本番の表示がどれだけ速くなるかは、測っていません。
増えた行の大半は、1.2.0 と同じタグの一覧を読むクエリの 404行でした。この行数はタグとカテゴリの数とともに増えます。タクソノミーまわりで読み取りが膨らんだ別の例は、タクソノミーの件数集計で D1 の読み取りが膨らんだ件に書きました。
coalesce: true を足す前にレイアウトと rows_read を見る
自分のサイトで coalesce: true を足すか決めるときは、次の点を確かめてください。
- レイアウトがタグとカテゴリの一覧やメニュー、ウィジェットを EmDash から読んでいるか。読んでいなければ、先読みした分は使われない
- タグとカテゴリが何件あるか。件数が多いほど、タグのクエリが読む行も増える
- 足す前と後で、トップページの
rows_readがどれだけ変わるか