一般来说影响数据库性能的因素主要可以分为两类:
业务需求 系统架构
实时count(*)
深翻页
无用功能堆积
不断需求升级造成系统复杂,影响整体性能
过度重视用户体验
至于系统架构可以从以下几方面考虑:
数据库中存放的数据是否都适合 大表是否拆分 是否合理的利用了Cache机制 数据层的实现是否都是最精简 超复杂的sql语句 过度依赖数据库Query语句功能导致效率低下 对扩展性过度追求,导致将对象拆的过于离散 重复执行相同的Query语句
先说数据库存放的数据是否合适,比如二进制音视频等富媒体数据、流水队列数据、超大文本数据。然后是对于大表是否有进行水平拆分。是否有合理的利用Cache机制,比如有没有将访问频繁且更新较少的数据放入Cache,具体来说有系统配置及规则数据、活跃用户的基本信息、活跃用户的个性化定制信息、准实时的统计信息。最后是数据层的实现是否都是最精简,举个具体的例子来说:
SELECT id,subject,url FROM photo WHERE user_id = 1 LIMIT 10
SELECT COUNT(*) FROM photo_comment WHERE photo_id = ?
SELECT photo_id, count(*) FROM photo_comment WHERE photo_id IN(?) GROUP BY photo_id
我们常说好的开始能决定好的结束,所以对于数据库性能这块来说,一个好的设计往往很大程度上能影响咱们数据库的性能。具体来说,我们可以从以下这些点着手:
适度冗余-尽量减少join 大字段垂直拆分 大表水平拆分 选用合适的数据类型
对于互联网应用来说我们应当尽量减少连表查询,适当的冗余。对于大字段,比如blob字段我们可以将其拆分存储在key-value存储之中,然后映射id字段到原表。
优化更需要优化的Query
定位优化对象的性能瓶颈
明确优化目标
从Explain入手
优化的基本原则
多使用Profile
永远用小结果集驱动大结果集,而非小表驱动大表
尽可能在索引中完成排序
只取自己需要的列
仅仅使用最有效的过滤条件
尽可能避免复杂的Join和子查询
为了性能或功能上的需要,可以使用MySQL的HINT,如果用FORCE INDEX强制使用某个索引
大量的排序操作影响性能,尽量减少ORDER BY,GROUP BY操作,可以使用程序替代
对于经常更新的字符串使用char而不要使用varchar
对容易产生碎片的表使用OPTIMIZE TABLE
关于索引优化这块我们可以从以下三点入手:
索引规范 方法技巧 注意事项
先来说索引规范:
适合添加索引的列应尽量满足如下条件: 出现在WHERE或ON中的列 具有较少的重复值 以查询操作为主,对于更新操作远远大于查询操作的列,不要创建索引(考虑索引维护的代价)
尽量使用短索引,短索引更容易被MySQL加载到内存中,从而达到提高读性能的目的,这点对主键尤其重要
更新频繁的表,数据量较小时尽量不要建立索引,过多的索引会导致插入、更新、删除,甚至于查询性能的下降
一般情况下不要使用FORCE INDEX强制使用某个索引,尽量让MySQL优化器决定使用哪个索引
建议尽量减少对主键索引的更新,这样会导致所有辅助索引的更新
建议做性能测试的时候根据需要禁止adaptive hash index
然后是一些基于经验的方法技巧:
较频繁的作为查询条件的字段可考虑创建索引 为写多读少的表创建索引时,请充分考虑索引对写性能的影响 SQL中尽量在索引里完成排序 对于B-Tree复合索引(多维索引),只有WHERE条件中包含最左前缀(复合索引中的第一列)时,MySQL才会利用该复合索引(除非索引列全部为数值类型时)
最后是一些注意事项:
唯一性太差的字段不适合单独创立索引,即使是频繁的作为查询条件 更新非常频繁的字段不适合建立索引 不出现在WHERE子句中的字段不该建立索引 WHERE子句中尽量不要使用LIKE '%Content%',以通配符开头的字符串不会使用索引 WHERE子句中需要使索引列独立。MySQL不会利用计算后的索引列(除非该索引列为数值类型的主索引)
行级锁
表级锁
页面锁
InnoDB支持行级锁,要合理利用InnoDB的行级锁
合理设计索引,让InnoDB在索引键上面加锁的时候尽可能准确,尽可能的缩小锁定范围,避免造成不必要的锁定而影响其他Query的执行
尽可能让所有的数据检索都通过索引来完成,从而避免InnoDB因为无法通过索引加锁而升级为表级锁
尽可能减少基于范围的数据检索过滤条件,避免为间隙锁带来的负面影响而锁定了不该锁定的记录
尽量控制事务的大小,减少锁定的资源量和锁定时间长度
范式与冗余没有绝对的对与错,取决于具体的设计需求和性能需求;
读多写少性能要求高的应用
可以采取加入冗余数据、牺牲范式、提升性能
可以放弃约束的使用,例如外键约束,提升性能
可以牺牲范式,减小记录数规模,如违背1NF,不遵守属性不可再分
负面影响:应用代码的复杂性增加,更新操作代码增大




