feat: add performance indexes for improved query efficiency
This commit is contained in:
parent
1a41ae2a8d
commit
da3114b85e
98
src/main/resources/db/migration/V0012__ADD_INDEXES.sql
Normal file
98
src/main/resources/db/migration/V0012__ADD_INDEXES.sql
Normal file
@ -0,0 +1,98 @@
|
||||
-- ============================================================
|
||||
-- V0012 — Add performance indexes
|
||||
-- ============================================================
|
||||
|
||||
-- mangas
|
||||
-- follow: findByFollowTrue() hot path for the scheduled follow-update task
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_follow ON mangas (follow);
|
||||
|
||||
-- state: natural filter (PENDING, ACTIVE, etc.)
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_state ON mangas (state);
|
||||
|
||||
-- adult: MangaSpecification always filters adult = false by default
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_adult ON mangas (adult);
|
||||
|
||||
-- score: MangaSpecification filters score >= ?
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_score ON mangas (score);
|
||||
|
||||
-- status: plain index for exact-match; functional index for LOWER(status) IN (...)
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_status ON mangas (status);
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_status_lower ON mangas (LOWER(status));
|
||||
|
||||
-- title: findByTitleIgnoreCase + LIKE search via LOWER(title)
|
||||
CREATE INDEX IF NOT EXISTS idx_mangas_title_lower ON mangas (LOWER(title));
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- images
|
||||
-- object_key: needed for the page-by-page IN-query in ImageCleanupTask
|
||||
CREATE INDEX IF NOT EXISTS idx_images_object_key ON images (object_key);
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- manga_contents
|
||||
-- manga_content_provider_id: FK join for every chapter lookup
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_contents_provider_id ON manga_contents (manga_content_provider_id);
|
||||
|
||||
-- (manga_content_provider_id, LOWER(url)): covers existsByMangaContentProvider_IdAndUrlIgnoreCase
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_contents_provider_url ON manga_contents (manga_content_provider_id, LOWER(url));
|
||||
|
||||
-- downloaded: ingestion pipelines filter on downloaded = false
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_contents_downloaded ON manga_contents (downloaded);
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- manga_content_images
|
||||
-- manga_content_id: findAllByMangaContent + existsByMangaContent_IdAndPosition
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_content_images_content_id ON manga_content_images (manga_content_id);
|
||||
|
||||
-- (manga_content_id, position): covers the position-existence check and ordered reads
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_content_images_content_position ON manga_content_images (manga_content_id, position);
|
||||
|
||||
-- image_id: FK into the 500k-row images table — cascade deletes and joins
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_content_images_image_id ON manga_content_images (image_id);
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- manga_content_provider
|
||||
-- manga_id: findByManga_IdAndContentProvider_Id + @OneToMany collection load
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_content_provider_manga_id ON manga_content_provider (manga_id);
|
||||
|
||||
-- LOWER(manga_title): existsByMangaTitleIgnoreCaseAndContentProvider_Id
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_content_provider_title_lower ON manga_content_provider (LOWER(manga_title));
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- manga_ingest_reviews
|
||||
-- content_provider_id: FK lookups and cascade deletes
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_ingest_reviews_provider_id ON manga_ingest_reviews (content_provider_id);
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- user_manga_content_read
|
||||
-- user_id alone: countByUser, countDistinctMangaByUser
|
||||
-- (The UNIQUE constraint on (user_id, manga_content_id) exists but a single-column index
|
||||
-- on user_id allows efficient count/scan queries without reading the full composite key.)
|
||||
CREATE INDEX IF NOT EXISTS idx_user_manga_content_read_user_id ON user_manga_content_read (user_id);
|
||||
|
||||
-- (user_id, created_at DESC): eliminates the sort step in findTop10ByUserOrderByCreatedAtDesc
|
||||
CREATE INDEX IF NOT EXISTS idx_user_manga_content_read_user_created ON user_manga_content_read (user_id, created_at DESC);
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- user_manga_follow
|
||||
-- user_id: findByUser, existsByUserAndManga
|
||||
CREATE INDEX IF NOT EXISTS idx_user_manga_follow_user_id ON user_manga_follow (user_id);
|
||||
|
||||
-- manga_id: findByManga, existsByManga
|
||||
CREATE INDEX IF NOT EXISTS idx_user_manga_follow_manga_id ON user_manga_follow (manga_id);
|
||||
|
||||
-- Composite unique: existsByUserAndManga / findByUserAndManga point lookups
|
||||
-- (no constraint existed on this table before)
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_user_manga_follow_user_manga ON user_manga_follow (user_id, manga_id);
|
||||
|
||||
-- ============================================================
|
||||
|
||||
-- manga_import_job
|
||||
-- status: MangaImportJobSpecification filters on status
|
||||
CREATE INDEX IF NOT EXISTS idx_manga_import_job_status ON manga_import_job (status);
|
||||
Loading…
x
Reference in New Issue
Block a user