Skip to content

feat: 경매장 거래 내역 기본 조회 시 인덱스 사용을 위한 쿼리 수정#88

Merged
dev-ant merged 2 commits into
devfrom
perf/auction-history-search
Jan 18, 2026
Merged

feat: 경매장 거래 내역 기본 조회 시 인덱스 사용을 위한 쿼리 수정#88
dev-ant merged 2 commits into
devfrom
perf/auction-history-search

Conversation

@dev-ant

@dev-ant dev-ant commented Jan 18, 2026

Copy link
Copy Markdown
Contributor

📋 상세 설명

  • 경매 이력 검색 쿼리 성능 개선을 위해 Deferred Join(Late Row Lookup) 패턴을 적용하여, ID를 먼저 조회한 후 필요한 데이터만 조인하도록 최적화
  • SortField, SortDirection enum 처리를 위한 커스텀 Spring Converter를 등록하는 WebConfig를 추가
  • 개발·디버깅 편의를 위해 application.yml에 p6spy SQL 로깅을 활성화하고, Java 컨벤션에 맞게 import 순서를 정리

📊 체크리스트

  • PR 제목이 형식에 맞나요 e.g. feat: PR을 등록한다
  • 코드가 테스트 되었나요
  • 문서는 업데이트 되었나요
  • 불필요한 코드를 제거했나요
  • 이슈와 라벨이 등록되었나요

📆 마감일

Close #87

@dev-ant dev-ant requested a review from Copilot January 18, 2026 11:40
@dev-ant dev-ant self-assigned this Jan 18, 2026
@dev-ant dev-ant added the ✨feature 새로운 기능 추가 label Jan 18, 2026
@github-actions

Copy link
Copy Markdown

✅ 테스트 결과 for PR

Build: success

🧪 테스트 실행 with Gradle
📈 Coverage: -0.00%

📁 테스트 결과
📁 커버리지 보고서 (HTML)

@codecov

codecov Bot commented Jan 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 26.31579% with 14 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../persistence/AuctionHistoryQueryDslRepository.java 0.00% 13 Missing ⚠️
...application/scheduler/AuctionHistoryScheduler.java 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements performance improvements for auction history search functionality through query optimization. The main changes include a deferred join (late row lookup) pattern for more efficient database queries, along with code style improvements by reorganizing import statements to follow Java conventions (standard library imports after third-party imports).

Changes:

  • Implemented deferred join pattern in AuctionHistoryQueryDslRepository to optimize search queries by fetching IDs first, then joining for full data
  • Added WebConfig to register custom Spring converters for SortField and SortDirection enums
  • Enabled p6spy SQL logging in application.yml for development/debugging purposes

Reviewed changes

Copilot reviewed 109 out of 109 changed files in this pull request and generated 3 comments.

File Description
src/main/resources/application.yml Enabled p6spy logging for SQL query monitoring
src/main/java/until/the/eternity/config/WebConfig.java New configuration class that registers custom enum converters for request parameter binding
src/main/java/until/the/eternity/auctionhistory/infrastructure/persistence/AuctionHistoryQueryDslRepository.java Refactored search method to use deferred join pattern - first query fetches IDs only, second query fetches full entities with joins
Multiple files (60+) Reorganized imports to follow Java conventions: third-party imports first, then standard library imports

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

datasource:
p6spy:
enable-logging: false
enable-logging: true

Copilot AI Jan 18, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enabling p6spy logging in the default application.yml will cause SQL logging to be enabled in production environments. This can have significant performance implications and may expose sensitive data in logs. Consider using a profile-specific configuration (e.g., application-dev.yml) or keeping this disabled by default.

Copilot uses AI. Check for mistakes.
Comment on lines +92 to 101
// 4-2단계: ID로 상세 조회 (LEFT JOIN으로 옵션 포함)
List<AuctionHistory> content =
queryFactory
.selectFrom(ah)
.leftJoin(ah.auctionItemOptions, aio)
.fetchJoin()
.where(historyBuilder)
.where(ah.auctionBuyId.in(ids))
.orderBy(orderSpecifiers.toArray(new OrderSpecifier[0]))
.distinct() // 중복 제거
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.distinct()
.fetch();

Copilot AI Jan 18, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deferred join pattern implementation may not preserve the original ordering when fetching the detailed results in step 4-2. After retrieving IDs in a specific order, the second query fetches by ID with the same orderBy clause, but the IN clause doesn't guarantee order preservation. The results might be returned in a different order than the IDs list. Consider either: 1) Ordering the results in-memory based on the original IDs list order, or 2) Using a positional parameter to preserve the order from the first query.

Copilot uses AI. Check for mistakes.
List<OrderSpecifier<?>> orderSpecifiers = buildOrderSpecifiers(pageable, ah);

// 4단계: 모든 옵션과 함께 조회 (LEFT JOIN - 조건 없음!)
// 4단계: Deferred Join (Late Row Lookup) 패턴 적용

Copilot AI Jan 18, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deferred join pattern optimization lacks documentation explaining why this approach is used and what performance benefits it provides. Consider adding a comment block before step 4 that explains: 1) The purpose of the two-step query (Late Row Lookup pattern), 2) The performance benefit of fetching IDs first with index-only scan, 3) Any trade-offs or limitations of this approach.

Suggested change
// 4단계: Deferred Join (Late Row Lookup) 패턴 적용
/*
* 4단계: Deferred Join (Late Row Lookup) 패턴 적용
*
* 부분은 의도적으로 "2단계 쿼리" 사용하는 Late Row Lookup 패턴입니다.
* 1) 목적:
* - 4-1단계에서 JOIN 없이 필터/정렬 조건만 적용하여 ID(기본 ) 리스트만 먼저 조회합니다.
* - 4-2단계에서 조회된 ID들을 기준으로 실제 엔티티와 연관 관계(옵션) JOIN 하여 상세 데이터를 가져옵니다.
* - , 비용이 JOIN과 넓은 row 조회를 나중으로 미루어, 먼저 "어떤 row를 볼지" 가볍게 결정합니다.
*
* 2) 성능상의 이점:
* - 4-1단계 쿼리는 auctionBuyId 기준 인덱스를 활용한 (사실상) index-only scan에 가깝게 동작할 있습니다.
* - 단계에서는 조인/대량 컬럼 로딩 없이 ID만 조회하므로, 디스크 I/O와 네트워크 전송량이 줄어듭니다.
* - 페이징(offset/limit) 가벼운 쿼리에서 처리하여, 불필요한 조인 대상 row를 읽지 않게 됩니다.
* - 4-2단계는 이미 좁혀진 ID 집합에 대해서만 JOIN을 수행하므로, 전체 쿼리 비용이 줄어드는 효과가 있습니다.
*
* 3) 트레이드오프 / 한계:
* - 쿼리가 2 실행되므로, 네트워크 round-trip이 늘어납니다.
* - ID 리스트가 매우 커지는 경우(IN 절이 비대해지는 경우)에는 DB 또는 드라이버에 추가 부담을 있습니다.
* - 정렬/필터 조건은 4-1단계와 4-2단계에서 동일하게 유지되어야 하며,
* DB 스냅샷 일관성(동시성 업데이트) 측면에서 2번의 쿼리 사이에 약간의 시차가 존재할 있습니다.
* - 따라서, 패턴은 "JOIN이 많은/행이 많은 조회"에서 튜닝 목적의 선택적 최적화로 활용해야 합니다.
*/

Copilot uses AI. Check for mistakes.
@dev-ant dev-ant changed the title Perf/auction history search feat: 경매장 거래 내역 기본 조회 시 인덱스 사용을 위한 쿼리 수정 Jan 18, 2026
@dev-ant dev-ant merged commit 2fbccdc into dev Jan 18, 2026
8 checks passed
@dev-ant dev-ant deleted the perf/auction-history-search branch January 18, 2026 11:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨feature 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

경매장 거래 내역 기본 조회 시 인덱스 사용을 위한 쿼리 수정

2 participants