师兄问我如何处理慢SQL。我在学校作的小Demo里面数据量过小并无涉及到性能优化问题,可是思考这个问题倒以把数据库优化给捋一捋。ios
传统的学生思惟是很抽象的,好比一个SQL查询,当作是一个程序的执行,无非是想办法省内存,省磁盘空间,省CPU缓存,省调度,从这几个角度去想,这也是学生常常会回答的几条。sql
我以前的回答是这样的:数据库
上面说的对不对,大概来讲,确实是有道理的,但这么说能解决问题吗,恐怕不能。实际状况中咱们须要的首先不是解决方案,而是如何定位问题。一辆车子有异响,修理厂不去检查异响在哪里而是直接把四驱和引擎给换了一遍,这显然不对的。换个角度来讲,咱们首先要定位慢查询是缘由,仍是结果,而是否是上来就一顿优化。缓存
什么是慢查询,从使用的角度来说,感觉直接的是时间维度的消耗,一个查询的时间超过了你作基准测试时的时间,或者是这个时间让使用者不能接受,都算慢查询。安全
如何定位慢查询,从总体来看,一个查询要通过这么几步:性能优化
那么能够简单从上概括一下,慢查询的优化主要涉及:MYSQL自身的优化(Schema与数据类型的优化,建立高性能的索引,查询性能优化)和MYSQL的外部优化。在寻找问题的过程当中,须要在各个层面设置追踪点,肯定影响服务性能(我这里说的是整个服务而不只仅是SQL)是在哪里。若是肯定不是慢SQL的问题,测量的应该涉及服务器,客户端,网络这一块,慢查询的开始到结束的时间,若是是慢SQL的问题,那么测量的应该是SQL开始到结束的时间,而慢SQL的开始到结束的时间又分为开始到结束的时间又分为执行时间和等待时间。其中,执行时间由子任务时间,从每一个子任务时间咱们能够看到时间的占用状况,从而进行优化;等待时间则涉及系统间的影响和不一样任务之间占用磁盘的CPU的影响。服务器
回到我以前的回答,咱们依次捋一下,我说的这些回答是怎么具体问题具体分析。网络
硬件优化函数
这里说硬件优化可能过于狭隘,这一块应该不止是硬件优化,还有网络,应用层,操做系统。我就统一称为外部环境优化。这一部分涉及三条:性能
1.操做系统优化
2.硬件优化
3.应用层优化
4.网络配置
我主要讲一下硬件优化和网络配置,之后的再补。
硬件优化。许多不一样的硬件均可以影响MYSQL的性能,可是最多见的俩个瓶颈应该是CPU和I/O资源。
CPU能够经过查看CPU占用来观察,我前面只讲了时间的消耗,那么要不要讲性能的消耗,我以为能够,可是不是必要的,好比MYSQL对服务器CPU、内存的占用率,占用率很好是好事吗?我以为是好事,这意味着服务器上更多的资源分配给了MYSQL,可是CPU的总利用率一直很高并且影响到了服务性能,就该考虑是否是要换CPU了。
I/O能够经过操做系统中的I/O统计指令,如iostat来观察。配置大量内存的最大缘由并非由于能够在内存中保存大量数据,而是为了不磁盘I/O。虽然咱们可使用索引来避免随机I/O,可是使用缓存即便是随机读取也能够省更多的操做,一个设计良好的数据库缓存能够提升很好的工做效率。
须要注意的是,并非足够的内存就能够彻底避免磁盘的读取请求,在服务器重启之后有时会出现读取速度慢的时候,是由于服务器的缓存尚未“热”起来,并且虽然读写能够在内存中完成,可是写的持久化依然要进行磁盘I/O。
针对缓存,通常可使用以下的方法:
1.屡次写入,一次刷新(好比计数器)
2.I/O合并,(不一样部分的数据在内存中修改,经过一次操做合并到一块儿完成持久化)
硬盘有延迟和吞吐量,网络也是。延迟和带宽一般是网络链接的限制因素,但更大的问题是出如今延迟上。由于TCP会尝试重发,由于它的安全机制,由于TCP会积压,由于它的链接队列(这里能够修改MYSQL的back_log)。一个应用程序一般会传输不少很小的网络包,最后每次传输的轻微延迟最终都会被累加起来,而不正常的网络形成的丢包也会形成一样的问题。
另外一个问题出如今DNS的损坏,由于当MYSQL收到一个链接请求时,它同时须要作正向查找和反向DNS查找。当问题出现时,会致使链接拒绝,严重至关于遭到了DDOS攻击。所以在判断这一块的问题的时候,首先要监控网络性能和网络端口,若是DNS出现了问题,修改DNS,若是网络出现了问题,联系运营商或者修改网络设置。
使用索引
使用索引必定会提升查询效率吗,准确的说,应该是高性能的索引。要理解索引是如何工做的,首先在索引中找到对应的值,而后根据匹配的索引记录找到对应的数据行。
索引涉及的东西好多,我过一阵子再写。
-------
下面是草稿
使用索引:
通常你们能想到的就是使用索引了。可是要避免全表扫描,首先考虑在where,order by,group by 涉及的列上创建索引。
优化SQL语句:
经过explain,能够看到SQL的执行效果,从而选择更好的索引和优化查询语句。好比:explain selext * from student。
查询的时候不要用 * 号,这样会返回你用不到的字段,最好是用具体的字段替代。
不在索引列上作运算或者使用函数。
查询的时候尽可能使用 limit 减小返回的行数。
优化数据库对象:
使用 procedure analyse() 函数对表进行分析,这个函数能够对表中列的数据类型提出优化建议。表的数据类型的第一个原则是,能正确表示和存储数据的最短类型。能小就小。好比:select * from student procedure analyse()。
分表。若是一个表中有些列经常使用有些不经常使用,就垂直拆分,即把主键和一些列放在一个表中,把主键和另一些列放在另外一个表总。若是都经常使用,这个一个表又太大了,那就按行拆分,大表拆小表,也叫水平拆分。
中间表。若是要常常对一个表进行aggregation,那么我能够把这些结果用一个中间表存起来,这个也能够理解成另外一种程度的分表。
分区。分区就是把一个表分红多个区块,这个区块能够在一个磁盘上,也能够
硬件优化:
这个时候就是能用钱解决的东西就用钱解决,更好的CPU,更大的内存,性能更强的SSD。
MySQL自身优化:
在安装Mysql的时候,里面还有一个my.cnf配置文件,里面能够对各项参数进行优化调整,好比加大MySql的查询缓存,加大数据库链接池。
Schema与数据类型优化的我的理解
良好的表的设计能够节省后期的维护成本。我在参与数据库开发的过程当中数据量过小了,彷佛也没有死扣细节以尽量地提高查询地性能。
数据类型优化细节:
MySQL支持地数据类型特别多,可是一般咱们要从这么几个方面考虑咱们是要如何使用数据类型:
1.能正确存储数据地最小地数据类型。好比:若是字符串大小是一个定长的值,或者很是短的列,使用char会比varchar更有效率,好比存储一个Y/N值时,char只须要一个字节,而varchar(1)须要俩个字节,由于还须要以恶搞记录长度的额外字节。
2.简单地数据类型能存储地就不要用复杂地数据类型,好比:使用时间内建类型好比DATATIME或者TIMESAMP而不是字符串存储日期和时间,整形存储IP地址等。
3.避免NULL。好比:虽然不少表均可以包含NULL,可是若是是查询NULL列的时候可能会更复杂,好比当含NULL的列被索引时,每一个索引须要一个额外的字节。
必定要彻底范式化吗?在课堂上老师教的咱们建表须要知足三范式,即1.每列原子性 2.每列与主键相关 3.每列与主键列直接相关 。可是实际上建表的时候必定要保持范式化设计吗?咱们来看看范式的优势:当数据比较好的范式的时候,不多有多余的数据,表小,更新查找速度快。看起来挺不错,可是范式化设计的schema的缺点一般在关联上,稍微复杂一点的查询语句在符合范式的schema上可能至少须要一次关联,这也可能使得一些索引策略失效,好比范式化可能将列存放在不一样的表中,而这些列若是在一个表中原本能够数以一个索引。举个例子,若是我要查看vip用户的最近的10条信息:select message_text,user_name from message inner join user on message.user_id = user.id where user.account = vip order by message.published desc limit 10在这个查询中,Mysql首先须要扫描message中的published字段的索引,对于每一行找到的数据,都要在user表李检查这个用户是否是vip用户,若是只有一小部分用户的付费用户,那么效率是很是低下的。