系统卡的时候,第一反应往往是加内存。多数慢的根源是几条没走索引的查询,跟内存关系不大。先做哪块更划算?
先打开慢查询日志
慢的根源为什么常常不是内存?慢查询日志默认是关的,很多人不知道,出问题才去找原因,找不到。打开之后设个阈值,比如超过一秒就记下来,跑几天就有样本了。日志里能看到具体语句和执行时间,排序之后问题最严重的那几条一目了然。我们排过的案例里,前三条慢查询常常占了全部耗时的八成。先修这几条效果最明显。
看执行计划能知道为什么慢。是不是全表扫描、有没有用上索引跟扫描行数多少。有次一个查询扫了两百万行,加上索引之后只扫二十行,时间从三秒降到几毫秒。索引不是越多越好。写多读少的表加太多索引反而拖慢写入。我们一般按查询条件建联合索引,把最常用的字段放前面。建完要实测,别凭经验猜。
写法上的坑
有些查询慢是写法问题,加索引也没用。比如在字段上套函数、用模糊匹配开头通配和类型不一致导致隐式转换。这几种情况索引都失效,只能改写法或者加冗余字段。我们遇到过一个按手机号查订单的,字段是数字类型但传的是字符串,慢得离谱。改成类型一致之后立刻好了。看执行计划能看出来,看代码往往看不出。
分页也有坑。翻到第一万页的时候,数据库要先扫过前面所有行,越翻越慢。常见的改法是记住上一页末尾一条的标识。从那里往下取。深分页本身在产品上就有问题,用户真会翻到第一万页吗。我们一般建议限制最大页数。或者干脆换成筛选而不是翻页。既快又符合用户实际行为,没人用的功能不如砍掉。隐性的怎么算?
别忽略连接和锁
有时候慢不是查询本身,是被锁住了在等。长事务不提交,其他请求只能排队,表现就是整个系统卡顿。我们查过一个案例,一个忘记提交的事务挂了两小时,把库存表锁死。排查要看当前的连接和等待情况。别只盯着慢查询日志。连接池配置也要合理,太大反而增加数据库压力。这些属于运维常识,容易忽略。
数据库调优常见疑问
慢查询从哪里查起
先开启慢查询日志并设置阈值,按执行时间排序,优先修复耗时最高的几条语句。
加索引有什么讲究
按查询条件建联合索引并把常用字段前置,索引不宜过多,写入密集表尤其要克制。
深分页怎么优化
用上一页末尾一条记录的标识作为起点继续取,或限制最大页数、改用筛选条件。
总结:慢查询从日志和执行计划入手,改索引也改写法,注意深分页和锁等待,别一上来就加内存。