wordpress怎么远程保存图片大小googleseo新手怎么做
wordpress怎么远程保存图片大小,googleseo新手怎么做,网站建站方案说明书,wordpress 注册连接同事写了个SQL#xff0c;生产环境跑了8秒#xff0c;被DBA追着骂。
一看执行计划#xff0c;全表扫描#xff0c;100万行数据一行行扫。
“不是加了索引吗#xff1f;”
“加了#xff0c;但没用上。”
索引这东西#xff0c;加得不对比不加还糟糕。整理一下常见的索引…同事写了个SQL生产环境跑了8秒被DBA追着骂。一看执行计划全表扫描100万行数据一行行扫。“不是加了索引吗”“加了但没用上。”索引这东西加得不对比不加还糟糕。整理一下常见的索引坑。一、索引失效的常见场景1.1 对索引列做函数运算-- 索引失效SELECT*FROMordersWHEREYEAR(create_time)2024;-- 索引生效SELECT*FROMordersWHEREcreate_time2024-01-01ANDcreate_time2025-01-01;对索引列用函数优化器没法用索引。同理-- 失效SELECT*FROMusersWHEREUPPER(username)ADMIN;-- 如果经常这样查建函数索引MySQL 8.0CREATEINDEXidx_username_upperONusers((UPPER(username)));1.2 隐式类型转换-- phone是varchar类型-- 失效传入数字会发生隐式转换SELECT*FROMusersWHEREphone13812345678;-- 生效传入字符串SELECT*FROMusersWHEREphone13812345678;类型不匹配MySQL会做隐式转换相当于对列做了函数操作。1.3 前导模糊查询-- 失效SELECT*FROMproductsWHEREnameLIKE%手机%;-- 生效前缀匹配SELECT*FROMproductsWHEREnameLIKE手机%;%放前面没法用B树的有序性。解决方案用全文索引用Elasticsearch1.4 OR条件-- 假设只有name有索引age没有-- 失效SELECT*FROMusersWHEREname张三ORage25;-- 解决方案1给age也加索引-- 解决方案2改成UNIONSELECT*FROMusersWHEREname张三UNIONSELECT*FROMusersWHEREage25;OR条件会导致索引失效除非OR两边的列都有索引。1.5 不等于条件-- 可能失效取决于数据分布SELECT*FROMordersWHEREstatus!completed;-- 如果status只有几个值考虑改成SELECT*FROMordersWHEREstatusIN(pending,processing,failed);!和NOT IN通常无法利用索引或者即使用了也是全索引扫描。二、联合索引的坑2.1 最左前缀原则假设有索引idx_abc (a, b, c)-- 生效SELECT*FROMtWHEREa1;SELECT*FROMtWHEREa1ANDb2;SELECT*FROMtWHEREa1ANDb2ANDc3;SELECT*FROMtWHEREa1ANDc3;-- 只用到a-- 失效SELECT*FROMtWHEREb2;SELECT*FROMtWHEREc3;SELECT*FROMtWHEREb2ANDc3;联合索引必须从最左列开始使用中间不能跳过。2.2 范围查询后的列失效-- 索引idx_abc (a, b, c)-- c用不到索引SELECT*FROMtWHEREa1ANDb10ANDc3;-- 都能用到SELECT*FROMtWHEREa1ANDb10ANDc3;范围查询, , BETWEEN, LIKE会终止后续列的索引使用。设计索引时把等值查询的列放前面范围查询的列放后面。2.3 索引列顺序-- 查询1高频SELECT*FROMordersWHEREuser_id1ANDstatuspending;-- 查询2低频SELECT*FROMordersWHEREstatuspending;-- 正确设计user_id放前面CREATEINDEXidx_user_statusONorders(user_id,status);-- 如果反过来查询1能用但查询1效率差要扫描很多user_id高频查询的条件列放前面区分度高的列放前面。三、覆盖索引3.1 什么是覆盖索引-- 索引idx_user_id_name (user_id, name)-- 覆盖索引查询的列都在索引里不用回表SELECTuser_id,nameFROMusersWHEREuser_id1;-- 非覆盖需要回表取phoneSELECTuser_id,name,phoneFROMusersWHEREuser_id1;覆盖索引避免回表性能更好。3.2 利用覆盖索引优化COUNT-- 慢需要扫描主键索引SELECTCOUNT(*)FROMusers;-- 快选择最小的二级索引SELECTCOUNT(*)FROMusersFORCEINDEX(idx_status);MySQL会自动选择最小的索引来COUNT但有时选错了需要手动指定。四、索引设计原则4.1 选择性高的列优先选择性 不重复的值 / 总行数-- 查看列的选择性SELECTCOUNT(DISTINCTstatus)/COUNT(*)ASstatus_selectivity,COUNT(DISTINCTuser_id)/COUNT(*)ASuser_id_selectivityFROMorders;-- 假设结果-- status_selectivity: 0.00015个状态/10万行-- user_id_selectivity: 0.88万用户/10万行user_id选择性高更适合建索引。status选择性低单独建索引意义不大。4.2 短索引优先-- 对于很长的字符串可以只索引前缀CREATEINDEXidx_titleONarticles(title(20));-- 确定前缀长度保证足够的选择性SELECTCOUNT(DISTINCTLEFT(title,10))/COUNT(*)ASsel_10,COUNT(DISTINCTLEFT(title,20))/COUNT(*)ASsel_20,COUNT(DISTINCTtitle)/COUNT(*)ASsel_fullFROMarticles;前缀索引更短同样空间能存更多数据效率更高。4.3 避免冗余索引-- 冗余idx_a已经被idx_ab覆盖CREATEINDEXidx_aONt(a);CREATEINDEXidx_abONt(a,b);-- 不冗余idx_ba的顺序不同CREATEINDEXidx_abONt(a,b);CREATEINDEXidx_baONt(b,a);定期检查冗余索引-- MySQL 8.0SELECT*FROMsys.schema_redundant_indexes;4.4 避免过度索引索引不是越多越好占用磁盘空间插入/更新/删除都要维护索引优化器选择困难一般一个表不超过5-6个索引。五、EXPLAIN看执行计划5.1 关键字段EXPLAINSELECT*FROMordersWHEREuser_id1;字段含义关注点type访问类型const eq_ref ref range index ALLkey实际使用的索引是否用到预期索引rows预估扫描行数越小越好Extra额外信息Using index好Using filesort/temporary不好5.2 常见type解释-- ALL全表扫描最差EXPLAINSELECT*FROMusersWHEREage25;-- age没索引-- index全索引扫描EXPLAINSELECTidFROMusers;-- range范围扫描EXPLAINSELECT*FROMusersWHEREid100;-- ref非唯一索引等值查询EXPLAINSELECT*FROMordersWHEREuser_id1;-- eq_ref唯一索引等值查询EXPLAINSELECT*FROMusersWHEREid1;-- const主键/唯一索引等值最多一行EXPLAINSELECT*FROMusersWHEREid1;5.3 Extra信息-- Using index覆盖索引好-- Using where用了WHERE过滤正常-- Using temporary用了临时表需要优化-- Using filesort用了文件排序需要优化看到Using temporary或Using filesort基本都要优化。六、真实案例案例1订单查询优化原SQL执行8秒SELECT*FROMordersWHEREuser_id12345ANDstatuspendingANDcreate_time2024-01-01ORDERBYcreate_timeDESCLIMIT20;EXPLAIN显示type: ALLrows: 1000000Extra: Using where; Using filesort问题没用到索引全表扫描文件排序。优化-- 建立联合索引CREATEINDEXidx_user_status_timeONorders(user_id,status,create_time);优化后EXPLAINtype: rangerows: 234Extra: Using index condition执行时间8ms案例2分页查询优化原SQLSELECT*FROMlogsORDERBYidDESCLIMIT100000,20;问题深分页要扫描10万行再丢弃。优化方案1记录上次ID-- 前端传上一页最小IDSELECT*FROMlogsWHEREid12345678ORDERBYidDESCLIMIT20;优化方案2延迟关联SELECTl.*FROMlogs lINNERJOIN(SELECTidFROMlogsORDERBYidDESCLIMIT100000,20)AStONl.idt.id;子查询只查ID覆盖索引再关联取全量数据。七、运维小技巧大表加索引会锁表生产环境要用pt-online-schema-change或gh-ost# pt-online-schema-changept-online-schema-change\--alterADD INDEX idx_user_id (user_id)\--execute\Dmydb,torders,hlocalhost我们有几个数据库在不同机房之前同步DDL操作很麻烦。现在用星空组网把几个节点连起来统一用Ansible批量执行就方便多了。总结索引设计核心原则原则说明最左前缀联合索引从左边开始匹配范围后失效范围查询列放最后覆盖索引查询列都在索引里最好选择性区分度高的列建索引不过度5-6个索引差不多了索引失效常见原因原因解决方案函数运算改写SQL或建函数索引类型转换保持类型一致前导模糊用全文索引/ESOR条件改UNION或都加索引不等于改写成IN索引优化这块经验欢迎交流~