mysql优化

*********************************************
数据库应用系统的优化真正能带来最大收益的就是商业需求和系统架构及业务实现的优化,然后是数据库Schema 设计的优化,然后才是Query 语句的优化,最后才是数据库管理软件自身的一些优化。通过笔者的经验,在整个系统的性能优化中,如果按照百分比来划分上面几个层面的优化带来的性能收益,可以得出大概如下的数据:
需求和架构及业务实现优化:55%
Query 语句的优化:30%
数据库自身的优化:15%
很多时候,大家看到数据库应用系统中性能瓶颈出现在数据库方面,就希望通过数据库的优化来解决问题,但不管DBA 对数据库多们了解,对Query 语句的优化多么精通,最终还是很难解决整个系统的性能问题。原因就在于并没有真正找到根本的症结所在。
所以,数据库应用系统的优化,实际上是一个需要多方面配合,多方面优化的才能产生根本性改善的事情。简单来说,可以通过下面三句话来简单的概括数据库应用系统的性能优化:商业需求合理化,系统架构最优化,逻辑实现精简化,硬件设施理性化。
*********************************************

商业需求对性能的影响
应用系统中的每一个功能在设计初衷肯定都是出于为用户提供某种服务,或者满足用户的某种需求,但是,并不是每一个功能在最后都能很成功,甚至有些功能的推出可能在整个系统中是画蛇添足。不仅没有为用户提高任何体验度,也没有为用户改进多少功能易用性,反而在整个系统中成为一个累赘,带来资源的浪费。不合理需求造成资源投入产出比过低需求是否合理很多时候可能并不是很容易界定,尤其是作为技术人员来说,可能更难以确定一个需求的合理性。即使指出,也不一定会被产品经历们认可。那作为技术人员的我们怎么来证明一个需求是否合理呢?

系统架构及实现对性能的影响
一个WEB 应用系统,自然离不开Web 应用程序(Web App)和应用程序服务器(AppServer)。AppServer 我们能控制的内容不多,大多都是使用已经久经考验的成熟产品,大家能做的也就只是通过一些简单的参数设置调整来进行调优,不做细究。而Web App 大部分都是各自公司根据业务需求自行开发,可控性要好很多。所以我们从Web 应用程序着手分析一个应用程序架构的不同设计对整个系统性能的影响将会更合适。

不适合在数据库中存放的:
1. 二进制多媒体数据
将二进制多媒体数据存放在数据库中,一个问题是数据库空间资源耗用非常严重,另一个问题是这些数据的存储很消耗数据库主机的CPU 资源。这种数据主要包括图片,音频、视频和其他一些相关的二进制文件。这些数据的处理本不是数据的优势,如果我们硬要将他们塞入数据库,肯定会造成数据库的处理资源消耗严重。
2. 流水队列数据
我们都知道,数据库为了保证事务的安全性(支持事务的存储引擎)以及可恢复性,都是需要记录所有变更的日志信息的。而流水队列数据的用途就决定了存放这种数据的表中的数据会不断的被INSERT,UPDATE 和DELETE,而每一个操作都会生成与之对应的日志信息。在MySQL 中,如果是支持事务的存储引擎,这个日志的产生量更是要翻倍。而如果我们通过一些成熟的第三方队列软件来实现这个Queue 数据的处理功能,性能将会成倍的提升。
3. 超大文本数据
对于5.0.3 之前的MySQL 版本,VARCHAR 类型的数据最长只能存放255 个字节,如果需要存储更长的文本数据到一个字段,我们就必须使用TEXT 类型(最大可存放64KB)的字段,甚至是更大的LONGTEXT 类型(最大4GB)。而TEXT 类型数据的处理性能要远比VARCHAR 类型数据的处理性能低下很多。从5.0.3 版本开始,VARCHAR 类型的最大长度被调整到64KB 了,但是当实际数据小于255Bytes 的时候,实际存储空间和实际的数据长度一样,可一旦长度超过255 Bytes 之后,所占用的存储空间就是实际数据长度的两倍。
所以,超大文本数据存放在数据库中不仅会带来性能低下的问题,还会带来空间占用的浪费问题。是否合理的利用了应用层Cache 机制?对于Web 应用,活跃数据的数据量总是不会特别的大,有些活跃数据更是很少变化。对于这类数据,我们是否有必要每次需要的时候都到数据库中去查询呢?如果我们能够将变化相对较少的部分活跃数据通过应用层的Cache 机制Cache 到内存中,对性能的提升肯定是成数量级的,而且由于是活跃数据,对系统整体的性能影响也会很大。
当然,通过Cache 机制成功的案例数不胜数,但是失败的案例也同样并不少见。如何合理的通过Cache 技术让系统性能得到较大的提升也不是通过寥寥几笔就能说明的清楚,这里我仅根据以往的经验列举一下 什么样的数据适合通过Cache 技术来提高系统性能
1. 系统各种配置及规则数据;
由于这些配置信息变动的频率非常低,访问概率又很高,所以非常适合存使用Cache;
2. 活跃用户的基本信息数据;
虽然我们经常会听到某某网站的用户量达到成百上千万,但是很少有系统的活跃用户量能够都达到这个数量级。也很少有用户每天没事干去将自己的基本信息改来改去。更为重要的一点是用户的基本信息在应用系统中的访问频率极其频繁。所以用户基本信息的Cache,很容易让整个应用系统的性能出现一个质的提升。
3. 活跃用户的个性化定制信息数据;
虽然用户个性化定制的数据从访问频率来看,可能并没有用户的基本信息那么的频繁,但相对于系统整体来说,也占了很大的比例,而且变更皮律一样不会太多。从Ebay 的PayPal 通过MySQL 的Memory 存储引擎实现用户个性化定制数据的成功案例我们就能看出对这部分信息进行Cache 的价值了。虽然通过MySQL 的Memory 存储引擎并不像我们传统意义层面的Cache 机制,但正是对Cache 技术的合理利用和扩充造就了项目整体的成功。

4. 准实时的统计信息数据;
所谓准实时的统计数据,实际上就是基于时间段的统计数据。这种数据不会实时更新,也很少需要增量更新,只有当达到重新Build 该统计数据的时候需要做一次全量更新操作。虽然这种数据即使通过数据库来读取效率可能也会比较高,但是执行频率很高之后,同样会消耗不少资源。既然数据库服务器的资源非常珍贵,我们为什么不能放在应用相关的内存Cache 中呢?

5. 其他一些访问频繁但变更较少的数据;
出了上面这四种数据之外,在我们面对的各种系统环境中肯定还会有各种各样的变更较少但是访问很频繁的数据。只要合适,我们都可以将对他们的访问从数据库移到Cache 中。
我们的数据层实现都是最精简的吗?
从以往的经验来看,一个合理的数据存取实现和一个拙劣的实现相比,在性能方面的差异经常会超出一个甚至几个数量级。


========================================================================
IO 操作在数据库应用系统中是非常昂贵的资源。尤其是当这个功能的PV 较大的时候,
重复执行相同的SQL 造成资源浪费。即较少查询次数。

我们甚至可以连一次都不需要访问就获得所需要的“分组”名称。首先,侧栏中的“分组”列表是需要有名称的,我们为什么不能直接利用到呢?
当然,可能有些系统的架构决定了侧栏和主要内容显示区来源于不同的模板(或者其他结构),那么我们也完全可以通过在进入这个功能页面的链接请求中通过参数传入我们需要的“分组”名称。这样我们就可以完全不需要根据“项目”相关信息去数据库获取所属“分组”的信息,就可以完成相应需求了。


下面大概列举了一些较为常见的 架构设计实现不当带来的性能问题和资源浪费情况
1、Cache 系统的不合理利用导致Cache 命中率低下造成数据库访问量的增加,同时也浪费了Cache系统的硬件资源投入;
2、对系统过度依赖面向对象思想;
3、对可扩展性的过渡追求,促使系统设计的时候将对象拆得过于离散,造成系统中大量的复杂Join
语句,而MySQL Server 在各数据库系统中的主要优势在于处理简单逻辑的查询,这与其锁定的机制也有
较大关系;
4、对数据库的过渡依赖,将大量更适合存放于文件系统中的数据存入了数据库中,造成数据库资源的浪费,影响到系统的整体性能,如各种日志信息;
5、过度理想化系统的用户体验,使大量非核心业务消耗过多的资源,如大量不需要实时更新的数据做了实时统计计算。
以上仅仅是一些比较常见的症结,在各种不同的应用环境中肯定还会有很多不同的性能问题,可能需要大家通过仔细的数据分析和对系统的充分了解才能找到,但是一旦找到症结所在,通过相应的优化措施,所带来的收益也是相当可观的。


Query 语句对系统性能的影响


为什么返回完全相同结果集的不同SQL 语句,在执行性能方面存在差异呢?这里我们先从SQL 语句在
数据库中执行并获取所需数据这个过程来做一个大概的分析了。
当MySQL Server 的连接线程接收到Client 端发送过来的SQL 请求之后,会经过一系列的分解
Parse,进行相应的分析。然后,MySQL 会通过查询优化器模块(Optimizer)根据该SQL 所设涉及到的数据表的相关统计信息进行计算分析,然后再得出一个MySQL 认为最合理最优化的数据访问方式,也就是我们常说的“执行计划”,然后再根据所得到的执行计划通过调用存储引擎借口来获取相应数据。然后再将存储引擎返回的数据进行相关处理,并以Client 端所要求的格式作为结果集返回给Client 端的应用程序。
一般来说, Query 语句的优化思路和原则主要提现在以下几个方面:
1. 优化更需要优化的Query;
2. 定位优化对象的性能瓶颈;
3. 明确的优化目标;
4. 从Explain 入手;
5. 多使用profile
6. 永远用小结果集驱动大的结果集;
7. 尽可能在索引中完成排序;
8. 只取出自己需要的Columns;
9. 仅仅使用最有效的过滤条件;
10. 尽可能避免复杂的Join 和子查询;
上面所列的几点信息,前面4 点可以理解为Query 优化的一个基本思路,后面部分则是我们优化中的基本原则。
==================


Schema 设计对系统的性能影响(表结构设计,数据模型设计)
数据库Schema 设计是一件非常简单的事情,就大体按照系统设计时候的相关实体对
象对应成一个一个的表格基本上就可以了。然后为了在功能上做到尽可能容易扩展,再根据数据库范式
规则进行调整,做到第三范式或者第四范式,基本就算完事了。
数据库Schema 设计真的有如上面所说的这么简单么?可以非常肯定的告诉大家,数据库Schema 设计
所需要做的事情远远不止如此。如果您之前的数据库Schema 设计一直都是这么做的,那么在该设计应用
于正式环境之后,很可能带来非常大的性能代价。

扩大内存容量来尽可能多的将活跃数据cache 到内存中;
选用每秒吞吐量尽可能大的磁盘;

当我们的CPU 处理能力足够的多,IO 系统的处理能力足够强的时候,如果我们
的应用架构和业务实现不够优化,一个本来很简单的实现非得绕很多个弯子来回交互多次,那再强的硬
件也没有用,因为来回的交互总是需要消耗时间。尤其是有些业务逻辑设计不是特别合理的应用,数据
库Schema 设计的不够合理,一个任务在系统中又被分拆成很多个步骤,每个步骤都使用了非常复杂的
Query 语句。笔者曾经就遇到过这样一个系统,该系统是购买的某知名厂商的一个项目管理软件。该系统最初运行在一台Dell2950 的PC Server 上面,使用者一直抱怨系统响应很慢,但我从服务器上面的状态来看系统并不繁忙(系统并发不是太大)。后来使用者强烈要求通过更换硬件设施来提升系统性能,虽然我一直反对,但最后在管理层的要求下,更换成了一台Sun 的S880 小型机,主机CPU 的处理能力至少是原来机器的3 倍以上,存储系统也从原来使用本地磁盘换成使用EMC 的中断存储CX300。可在试用阶段,
发现系统整体性能没有任何的提升,最终还是取消了更换硬件的计划。
所以,在应用系统的硬件配置方面,我们应该要以一个理性的眼光来看待,只有合适的才是最好
的。并不是说硬件资源越好,系统性能就一定会越好。而且,硬件系统本身总是有一个扩展极限的,如
果我们一味的希望通过升级硬件性能来解决系统的性能问题,那么总有一天将会遇到无法逾越的瓶颈。
到那时候,就算有再多的钱去砸也无济于事了。


合理利用锁机制优化MySQL
MyISAM 表锁优化建议
对于MyISAM 存储引擎,虽然使用表级锁定在锁定实现的过程中比实现行级锁定或者页级锁所带来的
附加成本都要小,锁定本身所消耗的资源也是最少。但是由于锁定的颗粒度比较到,所以造成锁定资源
的争用情况也会比其他的锁定级别都要多,从而在较大程度上会降低并发处理能力。
所以,在优化MyISAM 存储引擎锁定问题的时候,最关键的就是如何让其提高并发度。由于锁定级别
是不可能改变的了,所以我们首先需要尽可能让锁定的时间变短,然后就是让可能并发进行的操作尽可
能的并发。


================================

表的某个字段创建 索引,所带来的最大益处就是将该字段作为检索条件的时候
可以极大的提高检索效率,加快检索时间,降低检索过程中所需要读取的数据量,索引还有一个非常重要的用途,那就是降低数据的
排序成本。
索引并不是越多越好

◆ 更新非常频繁的字段不适合创建索引;
◆ 不会出现在WHERE 子句中的字段不该创建索引;
◆ 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件;

选择合适索引
的几点建议,并不一定在任何场景下都合适,但在大多数场景下还是比较适用的。
1. 对于单键索引,尽量选择针对当前Query 过滤性更好的索引;
2. 在选择组合索引的时候,当前Query 中过滤性最好的字段在索引字段顺序中排列越靠前越好;
3. 在选择组合索引的时候,尽量选择可以能够包含当前Query 的WHERE 子句中更多字段的索
引;
4. 尽可能通过分析统计信息和调整Query 的写法来达到选择合适索引的目的而减少通过使用
Hint 人为控制索引的选择,因为这会使后期的维护成本增加,同时增加维护所带来的潜在风险。
MySQL 中索引的限制
在使用索引的同时,我们还应该了解在MySQL 中索引存在的限制,以便在索引应用中尽可能的避开
限制所带来的问题。下面列出了目前MySQL 中索引使用相关的限制。
1. MyISAM 存储引擎索引键长度总和不能超过1000 字节;
2. BLOB 和TEXT 类型的列只能创建前缀索引;
3. MySQL 目前不支持函数索引;
4. 使用不等于(!= 或者<>)的时候MySQL 无法使用索引;
5. 过滤字段使用了函数运算后(如abs(column)),MySQL 无法使用索引;
6. Join 语句中Join 条件字段类型不一致的时候MySQL 无法使用索引;
7. 使用LIKE 操作的时候如果条件以通配符开始( '%abc...')MySQL 无法使用索引;
8. 使用非等值查询的时候MySQL 无法使用Hash 索引;
9.
在我们使用索引的时候,需要注意上面的这些限制,尤其是要注意无法使用索引的情况,因为这很
容易让我们因为疏忽而造成极大的性能隐患。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值