From 783788fc2ffb2cc80df22ef1f0b60aa9543b063d Mon Sep 17 00:00:00 2001 From: Kentaro Saida Date: Sat, 20 Jun 2026 17:19:59 +0900 Subject: [PATCH] =?UTF-8?q?perf(db):=20cf=5Fitems.subject=5Furi=20?= =?UTF-8?q?=E3=81=AB=20GIN=20=E7=B4=A2=E5=BC=95=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 分野の逆引き(この分野を設定している項目)で使う JSONB 包含クエリ subject_uri @> '[{"identifier": ...}]' を高速化する GIN(jsonb_path_ops) 索引を追加。大規模フレームワークでも seq scan を避ける。 - migration d1a2b3c4e5f6(down_revision c704faa62b4f) - cf_item.py の __table_args__ に同索引をミラー(autogenerate 整合) - db-schema.md(英/日)の cf_item 索引一覧に追記 逆引き機能(router/template)は後続 PR。索引のみ先行。 Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01XXFogp18twGiPFBAZcqJw2 --- docs/spec/db-schema.md | 2 ++ ...b3c4e5f6_gin_index_cf_items_subject_uri.py | 35 +++++++++++++++++++ src/models/cf_item.py | 7 ++++ 3 files changed, 44 insertions(+) create mode 100644 migrations/versions/d1a2b3c4e5f6_gin_index_cf_items_subject_uri.py diff --git a/docs/spec/db-schema.md b/docs/spec/db-schema.md index 4bbf751..c528948 100644 --- a/docs/spec/db-schema.md +++ b/docs/spec/db-schema.md @@ -99,6 +99,7 @@ last_change_date_time: TIMESTAMP NOT NULL UNIQUE(tenant_id, identifier) INDEX(tenant_id, cf_document_id, human_coding_scheme) -- for upsert matching INDEX(cf_document_id, depth) -- for the tree view's level detection (also covers `INDEX(cf_document_id)` alone) +GIN INDEX(subject_uri jsonb_path_ops) -- reverse lookup "items setting this subject": subject_uri @> '[{"identifier": ...}]' ``` ### cf_association @@ -348,6 +349,7 @@ last_change_date_time: TIMESTAMP NOT NULL UNIQUE(tenant_id, identifier) INDEX(tenant_id, cf_document_id, human_coding_scheme) -- upsertマッチング用 INDEX(cf_document_id, depth) -- ツリービューLevel判定用(INDEX(cf_document_id) 単独の用途もカバー) +GIN INDEX(subject_uri jsonb_path_ops) -- 分野逆引き「この分野を設定している項目」: subject_uri @> '[{"identifier": ...}]' ``` ### cf_association diff --git a/migrations/versions/d1a2b3c4e5f6_gin_index_cf_items_subject_uri.py b/migrations/versions/d1a2b3c4e5f6_gin_index_cf_items_subject_uri.py new file mode 100644 index 0000000..acd4b6c --- /dev/null +++ b/migrations/versions/d1a2b3c4e5f6_gin_index_cf_items_subject_uri.py @@ -0,0 +1,35 @@ +"""add GIN index on cf_items.subject_uri (jsonb_path_ops) + +Enables fast reverse lookup "which items set this subject" via the JSONB +containment query ``subject_uri @> '[{"identifier": ""}]'``. +``jsonb_path_ops`` is the smaller / faster GIN operator class for ``@>``. + +Revision ID: d1a2b3c4e5f6 +Revises: c704faa62b4f +Create Date: 2026-06-20 00:00:00.000000 + +""" +from typing import Sequence, Union + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "d1a2b3c4e5f6" +down_revision: Union[str, None] = "c704faa62b4f" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + op.create_index( + "ix_cf_items_subject_uri_gin", + "cf_items", + ["subject_uri"], + unique=False, + postgresql_using="gin", + postgresql_ops={"subject_uri": "jsonb_path_ops"}, + ) + + +def downgrade() -> None: + op.drop_index("ix_cf_items_subject_uri_gin", table_name="cf_items") diff --git a/src/models/cf_item.py b/src/models/cf_item.py index ef7d438..9a6e027 100644 --- a/src/models/cf_item.py +++ b/src/models/cf_item.py @@ -14,6 +14,13 @@ class CFItem(Base): UniqueConstraint("tenant_id", "identifier", name="uq_cf_items_tenant_identifier"), Index("ix_cf_items_tenant_document_coding", "tenant_id", "cf_document_id", "human_coding_scheme"), Index("ix_cf_items_document_depth", "cf_document_id", "depth"), + # Reverse lookup "items setting this subject": subject_uri @> '[{"identifier": ...}]'. + Index( + "ix_cf_items_subject_uri_gin", + "subject_uri", + postgresql_using="gin", + postgresql_ops={"subject_uri": "jsonb_path_ops"}, + ), ) id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)