短期治标,长期治本!
首先找到最伤害使用体验的
最伤害使用体验的是那些影响大部分用户经常使用的页面。有时候最慢的不一定是使用频率最高的,所以,最优先处理的应该是最伤害使用体验的。
然后再找到最慢的
使用 newrelic 之类的工具可以快速找到上述问题。
步骤一: 检查 Transactions 中的内容
通常选上面两个选项查看对应的问题页面。
步骤二:记录 Transactions 的网址(取样)
步骤三:Trouble Shooting 找到最昂贵的 SQL
步骤四:开 rack-mini-profiler 找到有问题的 code
数据库变慢的主要原因
一、 连线过多,忙不过来
- 数据库连线有上限,过多的 Query 会造成连线池被占满
- 每一笔连线都有延迟时间,尽量一次抓取降低连线查询时间
- 多数的问题是出在 for 循环造成的 N+1 Query
二、 查询太重,数据库被压死
- Table Scan
- 资料集太大
- 使用昂贵的 SQL 内建函数,如 count,sum,avg
- 注意 subquery
解法:
- count 可以上 counter cache
- AVG 与 SUM 可以捞出来资料,用 Ruby 代码算
- 任何动用 SQL 服务器的 CPU 资源都是昂贵的,想办法寻求使用 WEB 服务器的替代解法
原则:
。任何动用 SQL 服务器的 CPU 资源都是昂贵的,想办法寻求使用 WEB 服务器的替代解法
。Web Ram > Web CPU > SQL RAM > SQL CPU
三、 资料太多,内存被撑爆
- Table Scan
- select post.* (只 select 需要的栏位)
- JOIN 的资料集太大
四、 Index 效率太低
- Table Scan
使用很多 order 串接条件,又没有打 index 时系统就会 table scan 去找资料
table scan:如果图书馆没有索引系统,只好把所有书统统倒在地上一本一本找,当图书馆有几十万笔资料,这个 sql query 可能把 db 搞爆了,如果有索引,则可以快速找到。 - 作为 Index 的栏位成本过高
- Index 打错或效率不够好
解法:
针对需要索引的栏位打 index
选择效率好的栏位作索引,如果没有这个栏位,可以自己做一个
比如 updated_at 效率不好,可以加一个 updated_at_timestame (Integer 类型)
或者使用布尔值而不是 string 作为分类类型
查找原则:
- 找出连线数高的原因(可以请用户排队等)
- 找出 DB CPU 负荷重的原因
- 找出资料集大的原因
- 分析 Index 效率
调校原则
- 先降 Query 数
- 再降 DB CPU 使用量
- 降低资料集的范围
- 拆 query,不超过一层 join
- 必要时 + query
数据库有一百万笔资料,找出符合条件的十万笔删掉,会碰到的问题与解法?
- 不使用 Active Record
- find_in_batches
- transaction (如每 1000 笔一个 commit)
- delete_all (直接使用 sql,而不是 ARM )
- (或者可以搬运到另外一张表中、或者使用 delayed_job 之类的在后台慢慢执行)
相关 gem (sneaky-save,acts_as_archive)
网友评论