-- ============================================================
-- 数据库优化迁移脚本
-- 目的：
--   1. 将 drug_chunks.ivfflat 索引升级为 HNSW 索引（检索质量更高）
--   2. 清理冗余的 embedding(JSON) 列（实际检索用的是 vec pgvector 列）
--   3. 为 conversations.created_at 和 messages.created_at 添加索引（按时间排序查询）
--   4. 为 messages.feedback 添加索引（反馈查询过滤）
--   5. 为 conversations.created_at 添加降序索引（对话历史分页）
--   6. 为 messages.sources 创建 GIN 索引（来源检索）
-- 注意：此脚本可重复执行（IF NOT EXISTS / IF EXISTS）
-- ============================================================

BEGIN;

-- ------------------------------------------------------------
-- 1. 向量索引升级：IVFFlat → HNSW
--    HNSW 在召回率和查询延迟上都优于 IVFFlat，尤其适合中小规模数据集。
--    lists=10 的 IVFFlat 在数据量增长后检索质量会严重下降。
-- ------------------------------------------------------------
DROP INDEX IF EXISTS public.idx_drug_chunks_vec;
-- HNSW 参数：m=16（连接数），ef_construction=64（构建时搜索宽度）
CREATE INDEX IF NOT EXISTS idx_drug_chunks_vec
    ON public.drug_chunks USING hnsw (vec vector_cosine_ops)
    WITH (m = 16, ef_construction = 64);

-- ------------------------------------------------------------
-- 2. 清理冗余 embedding(JSON) 列
--    drug_chunks 表同时有 embedding(JSON) 和 vec(pgvector) 两份向量存储，
--    embedding 列完全冗余，从未被 Java/Python 后端使用。
--    先删除可能依赖该列的索引（实际无），再删除列。
-- ------------------------------------------------------------
ALTER TABLE public.drug_chunks DROP COLUMN IF EXISTS embedding;

-- ------------------------------------------------------------
-- 3. 时间排序索引（解决按时间排序查询的全表扫描问题）
-- ------------------------------------------------------------
-- 对话历史分页：ORDER BY created_at DESC
CREATE INDEX IF NOT EXISTS ix_conversations_created_at
    ON public.conversations USING btree (created_at DESC);

-- 消息列表按时间升序：ORDER BY created_at ASC
CREATE INDEX IF NOT EXISTS ix_messages_created_at
    ON public.messages USING btree (created_at ASC);

-- ------------------------------------------------------------
-- 4. 反馈查询索引（管理后台反馈列表过滤）
-- ------------------------------------------------------------
CREATE INDEX IF NOT EXISTS ix_messages_feedback
    ON public.messages USING btree (feedback)
    WHERE feedback IS NOT NULL;

-- ------------------------------------------------------------
-- 5. messages.sources GIN 索引（来源检索）
--    messages.sources 当前是 JSON 类型，先转为 JSONB 再建 GIN 索引
--    （JSON 不支持 GIN 索引，JSONB 支持）
-- ------------------------------------------------------------
DO $$
BEGIN
    -- 检查列类型是否为 json（需要转为 jsonb）
    IF EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_name = 'messages' AND column_name = 'sources'
          AND data_type = 'json'
    ) THEN
        ALTER TABLE public.messages ALTER COLUMN sources TYPE jsonb USING sources::jsonb;
        RAISE NOTICE '已将 messages.sources 从 json 转为 jsonb';
    END IF;
END $$;

CREATE INDEX IF NOT EXISTS ix_messages_sources_gin
    ON public.messages USING gin (sources);

-- ------------------------------------------------------------
-- 6. user_progress.last_study_at 索引（按最近学习时间排序）
-- ------------------------------------------------------------
CREATE INDEX IF NOT EXISTS ix_user_progress_last_study_at
    ON public.user_progress USING btree (last_study_at DESC)
    WHERE last_study_at IS NOT NULL;

COMMIT;

-- ============================================================
-- 验证脚本（执行后可查询以下语句确认优化结果）
-- ============================================================
-- 查看向量索引类型
-- SELECT indexname, indexdef FROM pg_indexes WHERE tablename = 'drug_chunks';
--
-- 确认 embedding 列已删除
-- SELECT column_name FROM information_schema.columns WHERE table_name = 'drug_chunks';
--
-- 查看所有新增索引
-- SELECT indexname, indexdef FROM pg_indexes
-- WHERE indexname IN (
--   'ix_conversations_created_at',
--   'ix_messages_created_at',
--   'ix_messages_feedback',
--   'ix_messages_sources_gin',
--   'ix_user_progress_last_study_at'
-- );
