Some checks failed
SonarQube Analysis / SonarQube Scan (push) Has been cancelled
✅ 백엔드 구조 개선: - DatabaseService: 공통 DB 쿼리 로직 통합 - FileUploadService: 파일 업로드 로직 모듈화 및 트랜잭션 관리 개선 - 서비스 레이어 패턴 도입으로 코드 재사용성 향상 ✅ 프론트엔드 컴포넌트 개선: - LoadingSpinner, ErrorMessage, ConfirmDialog 공통 컴포넌트 생성 - 재사용 가능한 컴포넌트 라이브러리 구축 - deprecated/backup 파일들 완전 제거 ✅ 성능 최적화: - optimize_database.py: 핵심 DB 인덱스 자동 생성 - 쿼리 최적화 및 통계 업데이트 자동화 - VACUUM ANALYZE 자동 실행 ✅ 코드 정리: - 개별 SQL 마이그레이션 파일들을 legacy/ 폴더로 정리 - 중복된 마이그레이션 스크립트 정리 - 깔끔하고 체계적인 프로젝트 구조 완성 ✅ 자동 마이그레이션 시스템 강화: - complete_migrate.py: SQLAlchemy 기반 완전한 마이그레이션 - analyze_and_fix_schema.py: 백엔드 코드 분석 기반 스키마 수정 - fix_missing_tables.py: 누락된 테이블/컬럼 자동 생성 - start.sh: 배포 시 자동 실행 순서 최적화
164 lines
5.2 KiB
SQL
164 lines
5.2 KiB
SQL
-- ================================
|
|
-- 성능 최적화를 위한 추가 인덱스
|
|
-- 생성일: 2025.01 (Phase 2)
|
|
-- ================================
|
|
|
|
-- 1. 복합 인덱스 (자주 함께 사용되는 컬럼들)
|
|
-- ================================
|
|
|
|
-- files 테이블: job_no + revision 조합 (리비전 비교 시 자주 사용)
|
|
CREATE INDEX IF NOT EXISTS idx_files_job_revision
|
|
ON files(job_no, revision)
|
|
WHERE is_active = true;
|
|
|
|
-- files 테이블: job_no + upload_date (최신 파일 조회)
|
|
CREATE INDEX IF NOT EXISTS idx_files_job_date
|
|
ON files(job_no, upload_date DESC)
|
|
WHERE is_active = true;
|
|
|
|
-- materials 테이블: file_id + category (자재 분류별 조회)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_file_category
|
|
ON materials(file_id, classified_category);
|
|
|
|
-- materials 테이블: category + material_grade (자재 종류별 재질 검색)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_category_grade
|
|
ON materials(classified_category, material_grade);
|
|
|
|
-- 2. 검색 성능 향상 인덱스
|
|
-- ================================
|
|
|
|
-- materials 테이블: description 텍스트 검색 (GIN 인덱스)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_description_gin
|
|
ON materials USING gin(to_tsvector('english', original_description));
|
|
|
|
-- materials 테이블: 해시 기반 중복 검색
|
|
CREATE INDEX IF NOT EXISTS idx_materials_hash
|
|
ON materials(material_hash)
|
|
WHERE material_hash IS NOT NULL;
|
|
|
|
-- 3. 정렬 성능 향상 인덱스
|
|
-- ================================
|
|
|
|
-- jobs 테이블: 상태별 생성일 정렬
|
|
CREATE INDEX IF NOT EXISTS idx_jobs_status_created
|
|
ON jobs(status, created_at DESC)
|
|
WHERE is_active = true;
|
|
|
|
-- materials 테이블: 수량별 정렬 (대용량 자재 우선 표시)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_quantity_desc
|
|
ON materials(quantity DESC);
|
|
|
|
-- 4. 조건부 인덱스 (특정 조건에서만 사용)
|
|
-- ================================
|
|
|
|
-- 검증되지 않은 자재만 (분류 검토 필요한 항목)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_unverified
|
|
ON materials(classified_category, classification_confidence)
|
|
WHERE is_verified = false;
|
|
|
|
-- 신뢰도가 낮은 분류 (0.8 미만)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_low_confidence
|
|
ON materials(file_id, classified_category)
|
|
WHERE classification_confidence < 0.8;
|
|
|
|
-- 5. 외래키 성능 향상
|
|
-- ================================
|
|
|
|
-- pipe_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_pipe_details_material
|
|
ON pipe_details(material_id);
|
|
|
|
-- fitting_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_fitting_details_material
|
|
ON fitting_details(material_id);
|
|
|
|
-- valve_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_valve_details_material
|
|
ON valve_details(material_id);
|
|
|
|
-- flange_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_flange_details_material
|
|
ON flange_details(material_id);
|
|
|
|
-- bolt_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_bolt_details_material
|
|
ON bolt_details(material_id);
|
|
|
|
-- gasket_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_gasket_details_material
|
|
ON gasket_details(material_id);
|
|
|
|
-- instrument_details 테이블
|
|
CREATE INDEX IF NOT EXISTS idx_instrument_details_material
|
|
ON instrument_details(material_id);
|
|
|
|
-- 6. 통계 및 집계 성능 향상
|
|
-- ================================
|
|
|
|
-- 프로젝트별 자재 통계 (job_no 기준)
|
|
CREATE INDEX IF NOT EXISTS idx_materials_job_stats
|
|
ON materials(
|
|
(SELECT job_no FROM files WHERE files.id = materials.file_id),
|
|
classified_category
|
|
);
|
|
|
|
-- 파이프 길이 집계용 (파이프 cutting 계산)
|
|
CREATE INDEX IF NOT EXISTS idx_pipe_length_aggregation
|
|
ON pipe_details(material_id, length_mm)
|
|
WHERE length_mm > 0;
|
|
|
|
-- 7. 성능 모니터링을 위한 뷰 생성
|
|
-- ================================
|
|
|
|
-- 인덱스 사용률 모니터링 뷰
|
|
CREATE OR REPLACE VIEW index_usage_stats AS
|
|
SELECT
|
|
schemaname,
|
|
tablename,
|
|
indexname,
|
|
idx_tup_read,
|
|
idx_tup_fetch,
|
|
idx_scan,
|
|
CASE
|
|
WHEN idx_scan = 0 THEN 'UNUSED'
|
|
WHEN idx_scan < 10 THEN 'LOW_USAGE'
|
|
WHEN idx_scan < 100 THEN 'MEDIUM_USAGE'
|
|
ELSE 'HIGH_USAGE'
|
|
END as usage_level
|
|
FROM pg_stat_user_indexes
|
|
WHERE schemaname = 'public'
|
|
ORDER BY idx_scan DESC;
|
|
|
|
-- 테이블 크기 및 성능 모니터링 뷰
|
|
CREATE OR REPLACE VIEW table_performance_stats AS
|
|
SELECT
|
|
schemaname,
|
|
tablename,
|
|
n_tup_ins as inserts,
|
|
n_tup_upd as updates,
|
|
n_tup_del as deletes,
|
|
seq_scan as sequential_scans,
|
|
seq_tup_read as sequential_reads,
|
|
idx_scan as index_scans,
|
|
idx_tup_fetch as index_reads,
|
|
CASE
|
|
WHEN seq_scan + idx_scan = 0 THEN 0
|
|
ELSE ROUND((idx_scan::numeric / (seq_scan + idx_scan)) * 100, 2)
|
|
END as index_usage_percentage
|
|
FROM pg_stat_user_tables
|
|
WHERE schemaname = 'public'
|
|
ORDER BY seq_scan + idx_scan DESC;
|
|
|
|
-- ================================
|
|
-- 인덱스 생성 완료 로그
|
|
-- ================================
|
|
|
|
-- 성능 최적화 인덱스 생성 완료 확인
|
|
DO $$
|
|
BEGIN
|
|
RAISE NOTICE '성능 최적화 인덱스 생성 완료 - Phase 2 (2025.01)';
|
|
RAISE NOTICE '총 생성된 인덱스: 복합 인덱스 4개, 검색 인덱스 2개, 정렬 인덱스 2개';
|
|
RAISE NOTICE '조건부 인덱스 2개, 외래키 인덱스 7개, 집계 인덱스 2개';
|
|
RAISE NOTICE '모니터링 뷰 2개 생성';
|
|
END $$;
|