Skip to content

テーブル名を押したら中身を出す(1000 行ずつのページ送り) - #27

Merged
MR-TABATA merged 4 commits into
mainfrom
feat/data-paging
Sep 4, 2026
Merged

MR-TABATA merged 4 commits into
mainfrom
feat/data-paging

Conversation

@MR-TABATA

Copy link
Copy Markdown
Owner

押すと列の一覧が出ていました。マイグレーションを書いたのは自分なので、列の構成は知っています。押した動機は中身を見ることでした。

変えたこと

  • 既定タブを Data に。 列と索引は 1 クリック先
  • タブが操作をまたいで保たれる。 panel は htmx で丸ごと差し替わるので、列を 1 つ直すたびに先頭のタブへ弾き飛ばされていました。同じテーブルの中ではいま見ていたタブに留まり、別のテーブルへ移れば Data から始めます
  • 50 行で打ち切って 51 行目を見る手段が無かったのを、1000 行ずつのページ送りに(100 / 500 / 1000 / 5000 から選択)
rows 1–1,000  of about 2,360,335 (estimated from statistics)
page 1 of about 2,361            ← Prev / Next → / [1,000 rows ▾]

並び順は主キー

順序を指定しない LIMIT/OFFSET は速いのですが、PostgreSQL は行の順序を約束しません。めくると同じ行が二度出たり、どこにも出ない行ができます ── ページャの体裁で嘘をつくことになります。

実測(同梱の Airlines・236 万行):

ORDER BY 主キー  OFFSET 0          7 ms
                 OFFSET 100,000    86 ms
                 OFFSET 1,000,000  334 ms
                 OFFSET 2,359,000  878 ms   ← 最深部
順序なし         OFFSET 2,359,000  50 ms    ← 速いが正しくない

最深部で 878 ms なら払えます。主キーが無いテーブルでは並べようがないので、そう画面に書きます(⚠ No primary key — row order is not guaranteed between pages)。

総数は推定、次ページは実測

count(*) は開くたびの全走査になるので、総数は統計の推定を「約」と断って出します。

ただし 「次のページがあるか」は推定ではなく、返ってきた行数で決めます。 統計が古いと「次へ」が空振りし、それは総数が少しずれているより体験として悪いので。

入力の扱い

画面から来た page / rows は allow-list に通してから使います。壊れた値・負の値・一覧に無い大きさは黙って既定へ落とします(ここでエラーを出しても、利用者にできることが無いので)。

テスト

10 件追加、全体 315 件通過。翻訳は未訳 0 件。

E2E が 3 件落ちて、それがタブが保たれない問題を教えてくれました。 既定タブを変えたら列を触るテストが壊れ、直そうとしたら「操作のたびに Data へ戻る」ことが分かった、という順です。

🤖 Generated with Claude Code

https://claude.ai/code/session_01XkRWmyQf9Rt3sYjjkPSq4Y

MR-TABATA and others added 4 commits September 4, 2026 22:47
押すと列の一覧が出ていた。マイグレーションを書いたのは自分なので、列の構成は
知っている。**押した動機は中身を見ることだった。**

- 既定タブを Data にした。列と索引は 1 クリック先
- **タブが操作をまたいで保たれる。** panel は htmx で丸ごと差し替わるので、
  列を 1 つ直すたびに先頭のタブへ弾き飛ばされていた。同じテーブルの中では
  いま見ていたタブに留まり、別のテーブルへ移れば Data から始める
- 50 行で打ち切って 51 行目を見る手段が無かったのを、**1000 行ずつのページ送り**に
  した(100 / 500 / 1000 / 5000 から選べる)

**並び順は主キー。** 順序を指定しない LIMIT/OFFSET は速いが、PostgreSQL は行の
順序を約束しないので、めくると同じ行が二度出たり、どこにも出ない行ができる ──
ページャの体裁で嘘をつくことになる。実測(Airlines・236 万行): 主キー順は先頭
7 ms・最深部 878 ms、順序なしは 50 ms だが正しくない。主キーが無いテーブルでは
並べようがないので、そう画面に書く。

**総数は統計の推定で、推定だと書く。** count(*) は開くたびの全走査になる。
ただし「次のページがあるか」は推定ではなく**返ってきた行数**で決める ──
統計が古いと「次へ」が空振りし、それは総数が少しずれているより体験として悪い。

画面から来た page / rows は allow-list に通してから使う。壊れた値は黙って既定へ
落とす(ここでエラーを出しても、利用者にできることが無い)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XkRWmyQf9Rt3sYjjkPSq4Y
**縦に 2 行詰めた。**

- 見出しの下の「4 列 · 最大 1000 行をプレビュー」を消した。行数はページャが
  「rows 1–1,000 of about 1,894,295」と正確に言うようになったので重複していて、
  **同じことを 2 か所で言うと、いつか片方が古くなる**
- 件数はタブのラベルへ移した(Columns 4 / Indexes 3)。切り替えなくても分かるので、
  要約行そのものが要らなくなる
- 間隔を space-y-5 → 3

**ナビの右側が空いていた。** ここに、いま開いているテーブル名を出す。#detail は
htmx で丸ごと入れ替わり、ブラウザの履歴にも残らないので、そうしないと現在地が
タイトルにしか無い。サイドバーの選択(Alpine の sel)を見ているだけなので、
サーバ往復も OOB swap も要らない。

**「— ホバーでセクションメニュー」は外した。** UI が自分の使い方を説明していた。

E2E のタブ選択は完全一致をやめて .subtab のクラスで取る(ラベルに件数が
入ったため)。315 件通過、未訳 0。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XkRWmyQf9Rt3sYjjkPSq4Y
`<div class="…" {# 説明 #} x-data="…">` と書いた。Django は**タグの属性の中の
`{#…#}` を注釈として解釈しない**ので、説明文がそのまま画面に出ていた。
ヘッダの真ん中に、私が書いた実装メモが表示されていた。2 か所やった。

`{% comment %}` に直し、置く場所もタグの外にした。HTML コメントでも画面には
出ないが、ソースには残るので使わない(他のテンプレートと揃える)。

目で見張るものではないので、テンプレートを走査して**タグの中に `{#` があれば
落ちる**テストを置いた。直す前の状態で detail.html:6 を名指しで捕まえることを
確認済み。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XkRWmyQf9Rt3sYjjkPSq4Y
1000 行あるので、ページ全体が動くと列名もページ送りも画面の外へ流れていた。

- グリッドを overflow-auto max-h-[60vh] にし、列名を sticky に。
  SQL ランナーと絞り込みの結果は既にそうなっていて、**ここだけ揃っていなかった**
- ページャも上に貼り付ける。1000 行を送った先で「いま何ページ目か」を
  見に戻るのに、上まで戻らなくていい

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XkRWmyQf9Rt3sYjjkPSq4Y
@MR-TABATA
MR-TABATA merged commit 2a32199 into main Sep 4, 2026
1 check passed
@MR-TABATA
MR-TABATA deleted the feat/data-paging branch September 4, 2026 14:08
MR-TABATA added a commit that referenced this pull request Sep 4, 2026
1.7.0 から入ったのは 3 本。

- テーブル一覧が空でないテーブルを「0 行」と言っていたのを直す(#26)
- 数えた数を 3 桁で区切る。データベースの値は区切らない(#26)
- テーブル名を押したら中身を出す。1000 行ずつのページ送り、タブの保持、
  現在地の表示、グリッドだけのスクロール(#27)

ロードマップの v1.8.0「見えていないものを見せる」は、テーブル一覧を pg_class
ベースへ、の一部(reltuples への切り替え)だけが済んだ状態。UNLOGGED の区別・
パーティションの親子・マテビュー・外部テーブルは残っている。版の名前と中身が
食い違うので、CHANGELOG は実際に入ったもので書いた。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XkRWmyQf9Rt3sYjjkPSq4Y
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant