是优化MySQL?还是使用缓存?
今天我想对一个Greenfield项目上可以采用的各种性能优化策略作一个对比。换句话来说,该项目既没有之前决策强加给它的各种约束限制,也没有被优化过。
从具体来说,我想比较的两种优化策略是优化MySQL与缓存。提前说明,这些优化是正交的,唯一让你选择其中一者而不是另一者的原因是他们都耗费了资源--开发时间。
一、优化MySQL
优化MySQL时,一般会先查看发送给mysql的查询语句,然后再运行explain命令。稍加审查后很常见的做法是增加索引或对模式做一些调整。
1.优点
- 一个经过优化的查询对于所有使用应用的用户来说都是快速的。由于索引通过对数复杂度的速度来检索数据(又名分制,比如你搜索一个电话簿,逐步缩小搜索范围),而且随着数据量的递增也能维持良好的性能。对一个未经索引化的查询的结果做缓存随着数据的增长有时候则有可能会表现得更差。随着数据的增长,那些未命中缓存的用户可能会得到很糟糕的体验,这样的应用是不可用的。
- 不需要担心缓存失效或缓存数据过期的问题。
- 可以简化技术架构,在开发环境下复制与工作会更加容易。
2.缺点
- 有一些查询不能光通过索引得到性能上的改善,可能还需要改变模式,这在某些情况下对于一些应用可能会很麻烦。
- 有些模式的更改可能用于反规范化(数据备份)。尽管对于DBA来说,这是一项常用的技术,它需要所有权以确保所有的地方都是由应用程序更新,或者需要安装触发器来保证这种变化。
- 一些优化手段可能是MySQL所特有的。如果底层软件被移植到多个数据库上工作,那么很难确保除了增加索引外一些更复杂的优化技术可以通用。
二、使用缓存
这种优化需要人来分析应用的实际情况,将处理代价昂贵的部分从MySQL中剥离出来用第三方缓存替代,例如memcached或Redis。
1.优点
- 对于一些MySql自身很难优化的查询来说缓存会工作地很好,比如大规模的聚合或者分组的查询。
- 对于提高系统的吞吐率来说缓存可能是个不错的方案。比如对于多人同时访问应用时响应速度很慢的情况。
- 缓存可能更容易构建在另一个应用之上。例如:你的应用可能是另一个用MySQL存储数据的软件包的前端,而要对这个软件包做任何数据库方面的改动非常难。
2.缺点
- 如果数据对外提供多种存取范式(例如,在不同的页面上用不同的形式展示),那么让缓存过期或者更新可能会很难,同时/或者可能需要容忍已过期的数据。一个可行的替代方案是设计一套更加精细的缓存机制,当然它也有缺点,那就 是多次获取缓存会增加时延。
- 缓存一个产生代价昂贵的对象对于那些未命中缓存的用户(见优化MySQL的优势#1)来说可能会产生潜在的性能差异。一些好的性能实践表明你应该尽量缩小用户之间的差异性,而不仅仅是平均化(缓存倾向于这么做)。
- 幼稚的缓存实现无力应对一些微妙的漏洞,比如雪崩效应。正确的策略是引入一定级别的锁来将缓存再生的请求序列化。
三、总结
一般情况下,建议用户先对MySQL进行优化,个人认为开始阶段最合适的解决方案。但从长期来看,大部分应用都会有一些用例需要一定程度上同时实现以上这些方案。