生产级机器学习系统:从模型部署到MLOps治理的实战指南
2026/6/18 19:06:01
以下是一些优化慢SQL的方法以及索引失效的常见场景:
-- 1) 看执行计划EXPLAINSELECTuser_id,status,created_atFROMordersWHEREuser_id=123ANDstatus=1ORDERBYcreated_atDESCLIMIT20;-- 2) 按过滤 + 排序列建立联合索引CREATEINDEXidx_orders_user_status_createdONorders(user_id,status,created_at);-- 3) 覆盖索引:只查索引里的列,减少回表EXPLAINSELECTuser_id,status,created_atFROMordersWHEREuser_id=123ANDstatus=1ORDERBYcreated_atDESCLIMIT20;-- 1) 子查询改 JOIN(示例)EXPLAINSELECTu.id,u.nameFROMusers uJOINorders oONo.user_id=u.idWHEREo.status=1;-- 2) 避免在索引列上做函数计算:用范围条件替代EXPLAINSELECT*FROMusersWHEREcreated_at>='2024-01-01'ANDcreated_at<'2025-01-01';-- 查看 InnoDB 缓冲池大小(单位:bytes)SHOWVARIABLESLIKE'innodb_buffer_pool_size';-- 开启慢查询日志并设置阈值(示例:生产环境请评估影响)SETGLOBALslow_query_log='ON';SETGLOBALlong_query_time=0.5;-- 按时间范围分区(示例:按月)CREATETABLEorders_p(idBIGINTPRIMARYKEY,created_atDATETIMENOTNULL,user_idBIGINTNOTNULL,amountDECIMAL(10,2)NOTNULL,KEYidx_user_created(user_id,created_at))PARTITIONBYRANGE(TO_DAYS(created_at))(PARTITIONp202501VALUESLESS THAN(TO_DAYS('2025-02-01')),PARTITIONpmaxVALUESLESS THAN MAXVALUE);-- phone 是 VARCHAR 且有索引EXPLAINSELECT*FROMusersWHEREphone=13800138000;EXPLAINSELECT*FROMusersWHEREphone='13800138000';SELECT * FROM users WHERE YEAR(created_at) = 2024;,这里对created_at列使用了YEAR函数。SELECT * FROM orders WHERE order_amount * 2 > 1000;,对order_amount列进行了乘法运算。-- created_at 有索引EXPLAINSELECT*FROMusersWHEREYEAR(created_at)=2024;EXPLAINSELECT*FROMusersWHEREcreated_at>='2024-01-01'ANDcreated_at<'2025-01-01';-- order_amount 有索引EXPLAINSELECT*FROMordersWHEREorder_amount*2>1000;EXPLAINSELECT*FROMordersWHEREorder_amount>500;<>或!=)操作符时,索引可能无法有效利用。因为数据库需要扫描大量的数据来确定不满足条件的记录。OR连接条件:当OR连接的多个条件中只有部分列有索引时,可能导致索引失效。例如SELECT * FROM products WHERE product_id = 100 OR product_name = 'Apple';,如果product_name列没有索引。SELECT * FROM users WHERE age > 30 AND name = 'John';,如果name列在age列之后进行范围查询,name列的索引可能不被使用。-- 不等于通常选择性较差EXPLAINSELECT*FROMtWHEREstatus!=1;-- OR:两边都要可用索引,否则容易回退EXPLAINSELECT*FROMproductsWHEREproduct_id=100ORproduct_name='Apple';-- 联合索引 (age, name):范围条件会影响后续列利用EXPLAINSELECT*FROMusersWHEREage>30ANDname='John';EXPLAINSELECT*FROMusersWHEREage=31ANDname='John';-- is_deleted 只有 0/1,选择性差;通常用组合索引提升过滤效果EXPLAINSELECT*FROMordersWHEREis_deleted=0ANDuser_id=123;ALTERTABLEusersMODIFYCOLUMNphoneVARCHAR(32)NOTNULL;ANALYZETABLEusers;OPTIMIZETABLEusers;