优化GetStoreRemainingRights性能索引.sql 6.61 KB
-- ============================================
-- 优化 GetStoreRemainingRights 方法性能的索引
-- ============================================
-- 说明:这些索引专门为统计门店剩余权益功能优化
-- 执行前请检查索引是否已存在,避免重复创建

-- ============================================
-- 1. lq_kd_pxmx (开单品项明细表) 索引
-- ============================================
-- 用于:查询开单品项总数、按会员分组统计、JOIN关联
-- 查询条件:F_IsEffective, F_MemberId, glkdbh

-- 索引1:用于F_MemberId IN查询和JOIN
-- MySQL 5.7以下版本请先检查索引是否存在,或直接执行(如果已存在会报错,可忽略)
CREATE INDEX idx_kd_pxmx_member_effective_glkdbh 
ON lq_kd_pxmx(F_IsEffective, F_MemberId, glkdbh);

-- 索引2:用于JOIN和按会员分组(补充索引,覆盖JOIN场景)
CREATE INDEX idx_kd_pxmx_glkdbh_member_effective 
ON lq_kd_pxmx(glkdbh, F_MemberId, F_IsEffective);

-- ============================================
-- 2. lq_kd_kdjlb (开单记录表) 索引
-- ============================================
-- 用于:按门店和时间范围过滤、JOIN关联
-- 查询条件:F_IsEffective, djmd, kdrq

-- 索引1:用于门店+时间范围查询(最常用)
CREATE INDEX idx_kd_kdjlb_store_date_effective 
ON lq_kd_kdjlb(djmd, kdrq, F_IsEffective);

-- 索引2:用于JOIN(补充,F_Id是主键可能不需要)
-- 如果F_Id是主键,则不需要此索引
-- CREATE INDEX IF NOT EXISTS idx_kd_kdjlb_id_effective 
-- ON lq_kd_kdjlb(F_Id, F_IsEffective);

-- ============================================
-- 3. lq_xh_pxmx (消耗品项明细表) 索引
-- ============================================
-- 用于:查询消耗品项总数、按会员分组统计、JOIN关联
-- 查询条件:F_IsEffective, F_MemberId, F_ConsumeInfoId

-- 索引1:用于F_MemberId IN查询和JOIN
CREATE INDEX idx_xh_pxmx_member_effective_consume 
ON lq_xh_pxmx(F_IsEffective, F_MemberId, F_ConsumeInfoId);

-- 索引2:用于JOIN场景(补充索引)
CREATE INDEX idx_xh_pxmx_consume_member_effective 
ON lq_xh_pxmx(F_ConsumeInfoId, F_MemberId, F_IsEffective);

-- ============================================
-- 4. lq_xh_hyhk (消耗会员耗卡表) 索引
-- ============================================
-- 用于:按门店和时间范围过滤、JOIN关联
-- 查询条件:F_IsEffective, md, hksj

-- 索引1:用于门店+时间范围查询(最常用)
CREATE INDEX idx_xh_hyhk_store_date_effective 
ON lq_xh_hyhk(md, hksj, F_IsEffective);

-- 索引2:用于JOIN(F_Id是主键则不需要)
-- CREATE INDEX IF NOT EXISTS idx_xh_hyhk_id_effective 
-- ON lq_xh_hyhk(F_Id, F_IsEffective);

-- ============================================
-- 5. lq_hytk_hytk (退卡记录表) 索引
-- ============================================
-- 用于:按门店和时间范围过滤、JOIN关联
-- 查询条件:F_IsEffective, md, tksj

-- 索引1:用于门店+时间范围查询(最常用)
CREATE INDEX idx_hytk_hytk_store_date_effective 
ON lq_hytk_hytk(md, tksj, F_IsEffective);

-- 索引2:用于JOIN(F_Id是主键则不需要)
-- CREATE INDEX IF NOT EXISTS idx_hytk_hytk_id_effective 
-- ON lq_hytk_hytk(F_Id, F_IsEffective);

-- ============================================
-- 6. lq_hytk_mx (退卡明细表) 索引
-- ============================================
-- 用于:JOIN关联、按会员分组统计
-- 查询条件:F_IsEffective, F_RefundInfoId, F_BillingItemId

-- 索引1:用于JOIN lq_hytk_hytk
CREATE INDEX idx_hytk_mx_refund_effective 
ON lq_hytk_mx(F_RefundInfoId, F_IsEffective);

-- 索引2:用于JOIN lq_kd_pxmx
CREATE INDEX idx_hytk_mx_billing_effective 
ON lq_hytk_mx(F_BillingItemId, F_IsEffective);

-- ============================================
-- 7. 复合索引(补充优化)
-- ============================================
-- 如果需要进一步优化,可以考虑以下复合索引

-- lq_kd_pxmx: 覆盖查询(包含F_ProjectNumber,避免回表)
-- 注意:此索引较大,请根据数据量决定是否创建
-- CREATE INDEX IF NOT EXISTS idx_kd_pxmx_cover 
-- ON lq_kd_pxmx(F_IsEffective, F_MemberId, glkdbh, F_ProjectNumber);

-- lq_xh_pxmx: 覆盖查询(包含F_ProjectNumber)
-- CREATE INDEX IF NOT EXISTS idx_xh_pxmx_cover 
-- ON lq_xh_pxmx(F_IsEffective, F_MemberId, F_ConsumeInfoId, F_ProjectNumber);

-- ============================================
-- 索引创建前的检查(避免重复创建)
-- ============================================
-- 执行以下SQL检查索引是否已存在:

-- SELECT 
--     TABLE_NAME,
--     INDEX_NAME,
--     GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as COLUMNS
-- FROM INFORMATION_SCHEMA.STATISTICS
-- WHERE TABLE_SCHEMA = DATABASE()
--     AND TABLE_NAME IN ('lq_kd_pxmx', 'lq_kd_kdjlb', 'lq_xh_pxmx', 'lq_xh_hyhk', 'lq_hytk_hytk', 'lq_hytk_mx')
--     AND INDEX_NAME LIKE 'idx_%'
-- GROUP BY TABLE_NAME, INDEX_NAME
-- ORDER BY TABLE_NAME, INDEX_NAME;

-- ============================================
-- 索引创建后的验证
-- ============================================
-- 执行以下SQL验证索引是否创建成功:

-- SELECT 
--     TABLE_NAME,
--     INDEX_NAME,
--     GROUP_CONCAT(COLUMN_NAME ORDER BY SEQ_IN_INDEX) as COLUMNS,
--     NON_UNIQUE,
--     CARDINALITY
-- FROM INFORMATION_SCHEMA.STATISTICS
-- WHERE TABLE_SCHEMA = DATABASE()
--     AND TABLE_NAME IN ('lq_kd_pxmx', 'lq_kd_kdjlb', 'lq_xh_pxmx', 'lq_xh_hyhk', 'lq_hytk_hytk', 'lq_hytk_mx')
--     AND INDEX_NAME LIKE 'idx_%'
-- GROUP BY TABLE_NAME, INDEX_NAME, NON_UNIQUE, CARDINALITY
-- ORDER BY TABLE_NAME, INDEX_NAME;

-- ============================================
-- 性能测试建议
-- ============================================
-- 1. 创建索引前,记录查询时间
-- 2. 创建索引后,使用相同参数重新测试
-- 3. 使用 EXPLAIN 分析查询计划,确认索引被使用
-- 4. 如果索引未被使用,检查WHERE条件顺序是否匹配索引列顺序

-- ============================================
-- 注意事项
-- ============================================
-- 1. 索引会占用存储空间,请定期监控
-- 2. 索引会影响INSERT/UPDATE性能,但查询性能提升显著
-- 3. 如果表数据量很大,创建索引可能需要较长时间
-- 4. 建议在业务低峰期执行索引创建
-- 5. MySQL不同版本的兼容性:
--    - MySQL 8.0+ 支持 CREATE INDEX IF NOT EXISTS
--    - MySQL 5.7及以下不支持 IF NOT EXISTS,需要先检查索引是否存在
--    本文件已移除 IF NOT EXISTS,如索引已存在会报错,可安全忽略
-- 6. 如果报错 "Duplicate key name",说明索引已存在,可以继续执行后面的语句