当数据量到达一定的量级之后,一般而言是10万。数据库mysql的索引将变得尤其的重要。
没有索引的话,mysql将会遍历整个表来查询满足的条件,大家想想遍历一遍1000万的数据需要多长的时间呢。
不过,在使用mysql的索引的时候,小小的注意几点可能会给存储性能以及执行查询和更新语句的性能带来很大的提高。
根据实际操作中的一些经验,总结几条如下:
1 只有需要用到了字段才为其简历索引,索引也是为占用存储空间的。如果索引过多的话,更新的时候也要更新索引部分的数据,性能就不怎么好了。
2 简短的字符串类的索引,如char、varchar、text的列而言,如果能够确定索引的长度的就确定索引的长度,不要使用一个长长的索引长度,性能影响很大
3 除了主键以为还可以使用unique索引,一一对应的索引的话,如果hash表其查询的性能肯定是卓越的。因为只需要o(1)的复杂度晒。
4 遵从mysql的最左前缀的复合索引规则,根据where语句中使用的方式来定义复合的索引。例如建立了这么一个复合的索引(col1,col2,col3),那么在where时可以使用的索引有where col1 = **或者where col1 = ** and col2 = **或者 where col1 = ** and col2 = ** and col3 = **
最后的话,explain你的sql语句看看是否使用到索引,如果没有,赶快去加上吧。
呵呵,还要注意一点哦,mysql提供的丰富多彩的字符串函数并不是一个很好的东东哦,这些函数应用在where中的列上时是不会使用到索引的。如 where ucase(col1) = ***,即使col1上有索引,由于使用了函数转换,mysql并不能使用上之前建立的索引值。
网站优化之数据库性能优化
数据库往往是很多站点的瓶颈,根据业务需要,根据使用需要,根据常用的sql语句去优化数据库往往能够得到一些事半功倍的效果
今天同学说它用的drp系统当有10来个并发用户时,就表现得很慢了,问我原因。
我初步定位一下,发现是数据库的问题。就我之前也曾遇到同样的问题,故总结一下,避免他人遇到同样的问题,少走弯路:
一天,你发现你的系统的并发能力下降,看看是不是你的数据库出问题了。
1 你的数据库的表是不是很大了,select count(*) from *** 看一下你的表中的记录数是不是太多了。
如果太多的话,建议你按照逻辑的分数据库,然后在表中寻找一个字段来进行分表,将每个表中的记录数减少。
在一个太多记录的表中进行查询和更新都是很低效率的,最简单的道理是会导致大量的读写磁盘操作。
2 查看表的定义,show create table ***,看看是不是你的表的字段上的索引建的太多了。
如果太多,建议合并或者去掉一些索引,过多的索引会让更新数据变慢,因为更新数据时还需要同时更新这些数据对应的索引信息。
对于一些需要查询或者group by的字段,加上索引。
3 上面两点你都做了,如果还没有改善,那么需要修改一下你的数据库服务器的配置了。
检查你服务器的并发设置,有的服务器默认的并发量是很小的。
将你的数据库服务器的查询cache设置大一些,索引cache也设置大一些,缓存cache设置大一些,每个连接的cache也设置大一些。
如果你的表不是很大,而且要求实时的相应的话,如用户信息,最好使用完全内存映射这样的模式,如mysql中内存。
4 做了上述优化,还是不行的话,看看你的操作系统的设置了,是不是你的操作系统对并发用户数的限制啥的。
5 如果你有很多的时间和精力,而且你的服务器读请求很多的话,给你的数据库服务器加个cache,让大量的读操作能够让cache来满足。
6 如果你没有很多的时间和精力,给你的数据库服务器做热备份,在热备份的机子上做读操作。
7 还是不行的话,看看是不是你的机子的硬件性能不好,是不是网络问题了,更换更好的硬件,选择更高的带块吧,这个是最好的方式了。
写在最后的话:
数据库的索引很重要,mysql的存储引擎的选择很重要。
1 对于数据量大的系统,每当你查询、order by等等操作的时候 ,尽量先explain一下你的sql语句,看看是否使用了索引。
mysql的索引是使用B树来建立索引的,所以对于多字段组合的复合索引,where条件中的字段是按照左优先的顺序来使用索引。
如果不明白的话,看看B树的数据结构就明白,只有从左到右的顺序来使用索引才能取得索引的效果。
2 对于并发量很大的请求,建议使用mysql的innodb这种存储引擎,基于行的lock锁,能够支持到较大并发的更新。一般常用的myisam是基于表锁的,这种引擎在
并发量很大的写操作方便基本不占任何的优势。
3 根据业务的需要,分库分表是很重要的,将数据量按照一定的规则来取模,将数据量变小,这样查询和插入都能够得到很好的速度。
4 如果你比较怕麻烦来根据mysql的show status来对mysql的配置参数进行优化,可以使用这位牛人写的脚本来帮助你进行处理
mysql的性能诊断利器:http://www.day32.com/MySQL/
5 如果上述还不能解决你的问题,那就在业务层借助memcached这样的cache来帮忙吧。尽量将请求从cache中获得数据,从而减少mysql的压力
网站优化之数据库优化
数据库在当前的各个网站中的地位是不言而喻的。但是对数据库关心的人却是比较少的。
如何去根据业务的需要建表,根据业务的需要去为特定的字段建立索引。
对于记录数量少于一万条的站点来岁,优化似乎是没有必要的,但是对于一个记录数量在十万条以上的站点,对于
数据库的优化就是势在必行的了。优化前后的效果也是会给你带来震撼和惊喜的。
目前web2.0的程序,很大瓶颈是数据库的吞度量。不过,如何才能确定系统的瓶颈是数据库呢,
因为只有确定数据库是整个系统的瓶颈,我们才有必要去优化他,毕竟,还有这么多需求等待我们去做。
如何确定数据库是瓶颈?
1 如果程序设计良好,有一个数据库操作逻辑层,可以从这个层的统计数据看到每个请求花费的时间,
如果平均时间已经不能让你容忍的话,数据库已经是瓶颈了。
2 在数据库的服务器上使用top命令,看看mysql服务器占用资源的情况,看看机子的平均负载。
如果服务器的平均负载已经很高,mysql占用了块100%的cpu资源,说明mysql服务器很忙了。
3 在数据库服务器上使用iostat命令,看看磁盘IO,如果block住的操作比较多的话,
说明数据库操作还是过于频繁了,磁盘都响应不急了。
4 建议打开mysql的慢查询日志,这样grep select看一下日志中的慢查询的数量,
如果数量较多,说明慢查询的数量很多,需要进行调整了。
5 如果有一天数据库无法插入了,需要检查一下数据库表是不是过大了。32位的操作系统上一个表
最大的容量是2^32这么大。
不过还是建议增加一个数据库操作的逻辑层,在数据库操作的前后记录下操作的时间,
进行统计上报,利用监控程序来报警相关负责人,这样可以及早的知道数据库是瓶颈,提前做出优化。
知道数据库是瓶颈了,如何来进行优化呢?
1 我们第一个想到是看看数据库的容量是不是太大了,如果数据库表太大的话,
索引文件也会比较大,每次的更新操作就会更加的费时。需要考虑进行分库和分表了。
分库分表按照一定的规则来对数据库中的记录进行分区来存储,一方面可以做到一定的
负载均衡,将请求平分下来,每个区段去独自承受;另一方面,分库分表可以使我们
存储和操作更多的数据。
不过分库分表需要多之前基于单库的程序进行修改,存在一定的风险,因此,在程序设计
之初就应该考虑到分库分表的需要,最好是将数据库操作层独立出来,便于扩展和更改。
2 如果数据库表不是很大,但是查询慢的话,我们需要检查一下我们的sql查询语句,
利用mysql的explain语句看看是不是使用了索引,如果没有使用索引,那我们需要在
相应的字段上建上索引,反复的使用explain,寻找到个一个合适的索引。
在建索引时需要考虑:
1)数据库的索引要做到越少越好
因为每次更新都需要更新索引,索引过多就会降低写入的速度
2)最窄的字段放在键的左边
这样提高了索引中每一个点的基数,带来更好的索引读写性能
3)尽量避免file sort排序、临时表和表扫描
对于大表,全表扫描会导致大量的磁盘IO的操作,会导致操作非常的缓慢
4)对于大表,尽量不要将索引建在字符串类型的列上,字符串的匹配是很费时的,需要
付出很高的性能代价,如果一定有必要,建议对字符串列进行hash后取一个整形的值来进行
索引。
3 如果更新操作有点慢,而读操作的响应要求不需要很及时的话,可以考虑利用mysql的主从
热备来分担读写的压力。
毕竟对数据库的操作,写少读多。因此,我们将对数据库的写操作放到mysql的主服务器上,
利用mysql的热备,我们在备份的数据库服务器上进行读操作,由于可以有多个热备mysql,
于是可以将读操作分布在多个热备上面,从而将读操作均衡开来,提高读操作的性能。
4 缓存的使用
缓存是一切后台程序的根本,因为80%的请求是对应20%的数据,我们只需要少量的内存将20%的
数据缓存起来,就可以大大的满足我们系统需求,何乐而不为呢。
1)mysql设置中尽量增加key cache,thread cache、查询的cache
2)在应用程序层增加一个memcached这样的通用cache
3)对于少量数据,但是操作频繁的表使用mysql提供的内存heap表,可以获得极高的写入和读取速度
5 数据库的设计上进行优化
对于传统的数据库设计我们讲究建模范式,避免数据的冗余从而导致脏数据。然而在我们实际的
应用中需要根据情况来使用第三范式的一些规则,对于一些频繁需要在多个地方出现的数据,如同
一个论坛这种用户和主题以及回复等有关联的应用中,如果我们将用户同主题和回复分开来存储,
每次查询一下一篇文章或者一个回复的情况都需要对用户表和主题表或者回复表进行联查,如果数据量
小的话,这样联查的性能还是可以接受的,如果表大一点,上了3、4十万以上的数据,联查的速度就
会比较慢了。
该范式化的地方需要进行范式化,但是还是需要根据情况来设计我们的表,从而达到性能和良好设计的折中。
其它的话:
1 对于数据库的操作建议分层处理,至少分为两层,一层是数据库操作的逻辑层,一层是数据库的cache层。
从一开始就考虑如此,可以很方便在未来对数据库进行划分部署、分库分表扩展
2 增加mysql的监控,监控mysql的慢查询日志,监控mysql的请求情况
3 根据自己的需要来选择mysql的存储引擎
myisam有较高的读写速度,但是由于表锁定,不能同时进行快速的读和写。
innodb支持事务,提供了行级的锁,但是为了使用事务,表空间会比较大,而且不支持全文索引
heap将表放到内存中,适合与表小而需要频繁操作的情况,如用户信息,其读写很快,但是不是持久的,
需要自己来写工具让其持久
4 mysql服务器的一些状态检测的命令
show slave status:可以看到主从同步的情况
show [full] processlist:可以看到mysql服务器的请求情况,如果发现lock情况很多,需要注意了
show status:可以看到mysql服务器的各种请求情况
针对mysql的优化还没有结束呢,这里还有很多优化的地方,后续会有专门的文章来介绍的!一起期待吧...