mysql在遇到严重性能问题时,一般都有这么几种可能:
1、索引没有建好;2、sql写法过于复杂;3、配置错误;4、架构级别;
1 索引没有建好
进入到MySQL安装目录/bin/mysql -hlocalhost -uroot -p
show full processlist 查看当前运行情况
可以看到当前正在执行的sql语句, 有执行的sql、数据库名、执行的状态、来自的客户端ip、所使用的帐号、运行时间等信息
(1)查看是否有sql语句卡住了
myisam存储引擎有可能有一个写入的线程会把数据表给锁定了,这条语句不结束则其它语句也无法运行,查看processlist里的time这一项, 看看是否有执行时间很长的语句
(2)大量相同的sql语句正在执行
desc(explain)检查
例: desc select * from user where uid=2; 可以看到key、rows和Extra。说明有使用主键索引来查询
key是指明当前sql会使用的索引,rows是返回的结果集大小,Extra一般会显示查询和排序的方式,如果没有使用到key,或者rows很大而用到了filesort排序,一般都会影响到效率
例:desc select * from user where name="apple" order by create_time desc limit 10; 假设有1W条, 可以看到有Extra,说明有排序,这时mysql执行时会把整个表扫描一遍,一条一条去找到匹配name="apple"的记录,然后还要对这些记录的create_time进行一次排序.... 这时可以把name加入索引,在把create_time加一个索引
注意: 如果查询的sql种类很多的话,就得好好规划一下了,否则索引会建得非常多,不但会影响到数据insert和update的效率,而且数据表也容易损坏
还有limit的条数尽量小一些
2 sql写法过于复杂
对于复杂类型的统计报表,能否折中处理,不显示实时数据, 显示隔天前的数据量, 在夜深人静的时候,查询出所需数据,载入缓存, 从缓存中取出使用
3 配置
key_buffer=128M:全部表的索引都会尽可能放在这块内存区域内,索引比较大的话就开稍大点都可以,我一般设为128M,有个好的建议是把很少用到并且比较大的表想办法移到别的地方去,这样可以显著减少mysql的内存占用
sort_buffer_size=1M:单个线程使用的用于排序的内存,查询结果集都会放进这内存里,如果比较小,mysql会多放几次,所以稍微开大一点就可以了,重要是优化好索引和查询语句,让他们不要生成太大的结果集
hread_concurrency=8:这个配置标配=cpu数量x2
wait_timeout=30:这两个配置使用10-30秒就可以了,这样会尽快地释放内存资源,注意:一直在使用的连接是不会断掉的,这个配置只是断掉了长时间不动的连接
query_cache:别动,要用就在只读型的数据库
4 架构级别问题
(1)数据同步:将数据同步到数台从数据库,由主数据库写入,从数据库提供读取, 但是需要注意不能出现数据错误
(2)加入缓存
(3)同时连接多个数据库, 分服务,拆分数据库