9

L1 제약·인덱스 구현과 정직한 한계

Neo4j 시작하기

학습 목표
  • 유일성 제약과 인덱스를 Cypher 로 구현한다
  • 존재성 제약이 Community 에서 불가능함을 확인하고 스펙을 개정한다
  • 인덱스를 CQ 의 WHERE 절에서 역산한다

L1 제약과 인덱스 구현

앞 모듈의 L1 목록을 Cypher로 구현합니다. 본편 환경(Community)에서 즉시 실행 가능합니다.

// 유일성 제약 (키 필드) — 제약 생성 시 인덱스 자동 생성
CREATE CONSTRAINT vessel_imo IF NOT EXISTS
FOR (v:Vessel) REQUIRE v.imoNumber IS UNIQUE;

CREATE CONSTRAINT container_no IF NOT EXISTS
FOR (c:Container) REQUIRE c.containerNumber IS UNIQUE;

CREATE CONSTRAINT port_locode IF NOT EXISTS
FOR (p:Port) REQUIRE p.unLocode IS UNIQUE;

CREATE CONSTRAINT portcall_id IF NOT EXISTS
FOR (pc:PortCall) REQUIRE pc.callId IS UNIQUE;

CREATE CONSTRAINT berth_code IF NOT EXISTS
FOR (b:Berth) REQUIRE b.berthCode IS UNIQUE;

여기서 정직한 한계 하나를 만납니다

앞 모듈 L1에 넣었던 존재성 제약("확정 이벤트는 actualTime을 반드시 가진다")은 Enterprise 전용 기능이라 Community에서는 걸 수 없습니다. Community의 DB 강제 수단은 사실상 유일성 제약까지입니다.

따라서 스펙을 개정합니다(v0.1 → v0.2): 존재성 제약은 L1에서 L2(ETL 검증)로 이관.

설계가 현실(에디션)을 만나 수정되는 첫 사례입니다. 개정 이력에 기록하세요 — 무엇이 왜 바뀌었는지 남기지 않으면, 나중에 "왜 여기만 ETL이 검증하지?"라는 질문에 아무도 답할 수 없습니다.

그리고 이것이 의사결정 트리에 네 번째 질문을 추가하는 근거입니다.

Q4. DB 수준의 데이터 무결성 강제(존재성·복합키)가 규제·감사 요건인가? → Yes면 Enterprise.

조회 성능 인덱스

// MVP CQ의 접근 패턴 기준
CREATE INDEX portcall_eta IF NOT EXISTS
FOR (pc:PortCall) ON (pc.etaBerth);              // PL-02: 48시간 입항 예정

CREATE INDEX event_actual IF NOT EXISTS
FOR (e:PortCallEvent) ON (e.actualTime);          // AN-01: 지연 탐지

CREATE INDEX event_source IF NOT EXISTS
FOR (e:PortCallEvent) ON (e.source);              // AN-10: 원천별 교차검증

CREATE POINT INDEX berth_position IF NOT EXISTS
FOR (b:Berth) ON (b.position);                    // 공간 질의 대비

CREATE FULLTEXT INDEX vessel_name_ft IF NOT EXISTS
FOR (v:Vessel) ON EACH [v.name];                  // 선명 검색 (코스 4 개체 연결)

인덱스 설계 원칙: CQ의 WHERE절이 인덱스 목록입니다. MVP 12선의 필터 조건(ETA 범위, 실제시각, 원천)을 먼저 걸고, 나머지는 코스 4에서 쿼리 프로파일링(PROFILE)으로 증거 기반 추가합니다.

⚠️ 미리 다 걸지 않습니다 — 인덱스는 쓰기 비용입니다.

에디터 로딩 중...
용어