`
xiangxingchina
  • 浏览: 523555 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MySql性能的检查和调优方法

阅读更多

转自:http://www.sudone.com/

我一直是使用mysql这个数据库软件,它工作比较稳定,效率也很高。在遇到严重性能问题时,一般都有这么几种可能:

1、索引没有建好;
2、sql写法过于复杂;
3、配置错误;
4、机器实在负荷不了;

1、索引没有建好

如果看到mysql消耗的cpu很大,可以用mysql的client工具来检查。

在linux下执行

/usr/local/mysql/bin/mysql -hlocalhost -uroot -p

输入密码,如果没有密码,则不用-p参数就可以进到客户端界面中。

看看当前的运行情况

show full processlist

可以多运行几次

这个命令可以看到当前正在执行的sql语句,它会告知执行的sql、数据库名、执行的状态、来自的客户端ip、所使用的帐号、运行时间 等信息

在我的cache后端,这里面大部分时间是看不到显示任何sql语句的,我认为这样才算比较正常。如果看到有很多sql语句,那么这台mysql就一定会有性能问题

如果出现了性能问题,则可以进行分析:

1、是不是有sql语句卡住了?

这是出现比较多的情况,如果数据库是采用myisam,那么有可能有一个写入的线程会把数据表给锁定了,如果这条语句不结束,则其它语句也无法运行。

查看processlist里的time这一项,看看有没有执行时间很长的语句,要留意这些语句。

2、大量相同的sql语句正在执行

如果出现这种情况,则有可能是该sql语句执行的效率低下,同样要留意这些语句。

然后把你所怀疑的语句统统集合一下,用desc(explain)来检查这些语句。

首先看看一个正常的desc输出:

mysql> desc select * from imgs where imgid=1651768337;
+—-+————-+——-+——-+—————+———+———+——-+——+——-+
| id | select_type | table | type  | possible_keys | key         | key_len | ref   | rows | Extra |
+—-+————-+——-+——-+—————+———+———+——-+——+——-+
|  1 | SIMPLE        | imgs | const| PRIMARY         | PRIMARY | 8            | const |   1 |          |
+—-+————-+——-+——-+—————+———+———+——-+——+——-+
1 row in set (0.00 sec)

注意key、rows和Extra这三项,这条语句返回的结果说明了该sql会使用PRIMARY主键索引来查询,结果集数量为1条,Extra没 有显示,证明没有用到排序或其他操作。由此结果可以推断,mysql会从索引中查询imgid=1651768337这条记录,然后再到真实表中取出所有 字段,是很简单的操作。

key是指明当前sql会使用的索引,mysql执行一条简单语句时只能使用到一条索引,注意这个限制;rows是返回的结果集大小,结果集就是使用该索引进行一次搜索的所有匹配结果;Extra一般会显示查询和排序的方式,。

如果没有使用到key,或者rows很大而用到了filesort排序,一般都会影响到效率,例如:

mysql> desc select * from imgs where userid=”7mini” order by clicks desc limit 10;
+—-+————-+——-+——+—————+——+———+——+——-+—————————–+
| id | select_type | table | type | possible_keys | key   | key_len | ref     | rows   | Extra   |
+—-+————-+——-+——+—————+——+———+——+——-+—————————–+
|  1 | SIMPLE        | imgs | ALL  | NULL               | NULL| NULL     | NULL | 12506 | Using where; Using filesort |
+—-+————-+——-+——+—————+——+———+——+——-+—————————–+
1 row in set (0.00 sec)

这条sql结果集会有12506条,用到了filesort,所以执行起来会非常消耗效率的。这时mysql执行时会把整个表扫描一遍,一条一条去 找到匹配userid=”7mini”的记录,然后还要对这些记录的clicks进行一次排序,效率可想而知。真实执行时如果发现还比较快的话,那是因为 服务器内存还足够将12506条比较短小的记录全部读入内存,所以还比较快,但是并发多起来或者表大起来的话,效率问题就严重了。

这时我把userid加入索引:

create index userid on imgs (userid);

然后再检查:

mysql> desc select * from imgs where userid=”7mini” order by clicks desc limit 10;
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
| id | select_type | table | type | possible_keys | key    | key_len | ref    | rows | Extra                       |
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
|  1 | SIMPLE        | imgs | ref   | userid              | userid| 51        | const |    8   | Using where; Using filesort |
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
1 row in set (0.00 sec)

嗯,这时可以看到mysql使用了userid这个索引搜索了,用userid索引一次搜索后,结果集有8条。然后虽然使用了filesort一条一条排序,但是因为结果集只有区区8条,效率问题得以缓解。

但是,如果我用别的userid查询,结果又会有所不同:

mysql> desc select * from imgs where userid=”admin” order by clicks desc limit 10;
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
| id | select_type | table | type | possible_keys | key     | key_len | ref     | rows  | Extra                       |
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
|  1 | SIMPLE        | imgs | ref   |       userid        | userid | 51         | const | 2944 | Using where; Using filesort |
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
1 row in set (0.00 sec)

这个结果和userid=”7mini”的结果基本相同,但是mysql用userid索引一次搜索后结果集的大小达到2944条,这2944条记 录都会加入内存进行filesort,效率比起7mini那次来说就差很多了。这时可以有两种办法可以解决,第一种办法是再加一个索引和判断条件,因为我 只需要根据点击量取最大的10条数据,所以有很多数据我根本不需要加进来排序,比如点击量小于10的,这些数据可能占了很大部分。

我对clicks加一个索引,然后加入一个where条件再查询:

create index clicks on imgs(clicks);

mysql> desc select * from imgs where userid=”admin” order by clicks desc limit 10;
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
| id | select_type | table | type | possible_keys | key     | key_len | ref     | rows | Extra                       |
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
|  1 | SIMPLE        | imgs | ref   |  userid,clicks   | userid | 51        | const | 2944 | Using where; Using filesort |
+—-+————-+——-+——+—————+——–+———+——-+——+—————————–+
1 row in set (0.00 sec)

这时可以看到possible_keys变成了userid,clicks,possible_keys是可以匹配的所有索引,mysql会从 possible_keys中自己判断并取用其中一个索引来执行语句,值得注意的是,mysql取用的这个索引未必是最优化的。这次查询mysql还是使 用userid这个索引来查询的,并没有按照我的意愿,所以结果还是没有什么变化。改一下sql加上use index强制mysql使用clicks索引:

mysql> desc select * from imgs use index (clicks) where userid=’admin’ and clicks>10 order by clicks desc limit 10
+—-+————-+——-+——-+—————+——–+———+——+——+————-+
| id | select_type | table | type  | possible_keys | key     | key_len |   ref   | rows | Extra       |
+—-+————-+——-+——-+—————+——–+———+——+——+————-+
|  1 | SIMPLE        | imgs | range|       clicks        | clicks |     4       | NULL | 5455 | Using where |
+—-+————-+——-+——-+—————+——–+———+——+——+————-+
1 row in set (0.00 sec)

这时mysql用到了clicks索引进行查询,但是结果集比userid还要大!看来还要再进行限制:

mysql> desc select * from imgs use index (clicks) where userid=’admin’ and clicks>1000 order by clicks desc limit 10
+—-+————-+——-+——-+—————+——–+———+——+——+————-+
| id | select_type | table  | type  | possible_keys | key    | key_len |  ref    | rows | Extra       |
+—-+————-+——-+——-+—————+——–+———+——+——+————-+
|  1 | SIMPLE        | imgs  | range|       clicks        | clicks|     4       | NULL |  312 | Using where |
+—-+————-+——-+——-+—————+——–+———+——+——+————-+
1 row in set (0.00 sec)

加到1000的时候结果集变成了312条,排序效率应该是可以接受。

不过,采用换索引这种优化方式需要取一个采样点 ,比如这个例子中的1000这个数字,这样,对userid的每个数值,都要去找一个采样点,这样对程序来说是很难办的。如果按1000取样的话,那么userid=’7mini’这个例子中,取到的结果将不会是8条,而是2条,给用户造成了困惑。

当然还有另一种办法,加入双索引

create index userid_clicks on imgs (userid, clicks)

mysql> desc select * from imgs where userid=”admin” order by clicks desc limit 10;
+—-+————-+——-+——+———————-+—————+———+——-+——+————-+
| id | select_type | table | type | possible_keys          |     key           | key_len | ref     | rows | Extra       |
+—-+————-+——-+——+———————-+—————+———+——-+——+————-+
|  1 | SIMPLE        | imgs |  ref  | userid,userid_clicks | userid_clicks | 51        | const | 2944 | Using where |
+—-+————-+——-+——+———————-+—————+———+——-+——+————-+
1 row in set (0.00 sec)

这时可以看到,结果集还是2944条,但是Extra中的filesort不见了。这时mysql使用userid_clicks这个索引去查询, 这不但能快速查询到userid=”admin”的所有记录,并且结果是根据clicks排好序的!所以不用再把这个结果集读入内存一条一条排序了,效率 上会高很多。

但是用多字段索引这种方式有个问题,如果查询的sql种类很多的话,就得好好规划一下了,否则索引会建得非常多,不但会影响到数据insert和update的效率,而且数据表也容易损坏。

以上是对索引优化的办法,因为原因可能会比较复杂,所以写得比较的长,一般好好优化了索引之后,mysql的效率会提升n个档次,从而也不需要考虑增加机器来解决问题了

但是,mysql甚至所有数据库,可能都不好解决limit的问题 。在mysql中,limit 0,10只要索引合适,是没有问题的,但是limit 100000,10就会很慢了,因为mysql会扫描排好序的结果,然后找到100000这个点,取出10条返回。要找到100000这个点,就要扫描 100000条记录,这个循环是比较耗时的。不知道会不会有什么好的算法可以优化这个扫描引擎,我冥思苦想也想不出有什么好办法。对于limit,目前直 至比较久远的将来,我想只能通过业务、程序和数据表的规划来优化,我想到的这些优化办法也都还没有一个是万全之策,往后再讨论。

2、sql写法过于复杂

sql写法假如用到一些特殊的功能,比如groupby、或者多表联合查询的话,mysql用到什么方式来查询也可以用desc来分析,我这边用复杂sql的情况还不算多,所以不常分析,暂时就没有好的建议。

3、配置错误

配置里主要参数是key_buffer、sort_buffer_size/myisam_sort_buffer_size ,这两个参数意思是:

key_buffer=128M:全部表的索引都会尽可能放在这块内存区域内,索引比较大的话就开稍大点都可以,我一般设为128M,有个好的建议是把很少用到并且比较大的表想办法移到别的地方去,这样可以显著减少mysql的内存占用。
sort_buffer_size=1M:单个线程使用的用于排序的内存,查询结果集都会放进这内存里,如果比较小,mysql会多放几次,所以稍微开大一点就可以了,重要是优化好索引和查询语句,让他们不要生成太大的结果集。

另外一些配置:
thread_concurrency=8:这个配置标配=cpu数量x2
interactive_timeout=30
wait_timeout=30:这两个配置使用10-30秒就可以了,这样会尽快地释放内存资源,注意:一直在使用的连接是不会断掉的,这个配置只是断掉了长时间不动的连接。
query_cache:这个功能不要使用,现在很多人看到cache这几个字母就像看到了宝贝,这是不唯物主义的。mysql的query_cache 在每次表数据有变化的时候都会重新清理连至该表的所有缓存,如果更新比较频繁,query_cache不但帮不上忙,而且还会对效率影响很大。这个参数只 适合只读型的数据库,如果非要用,也只能用query_cache_type=2自行用SQL_CACHE指定一些sql进行缓存。
max_connections:默认为100,一般情况下是足够用的,但是一般要开大一点,开到400-600就可以了,能超过600的话一般就有效率问题,得另找对策,光靠增加这个数字不是办法。

其它配置可以按默认就可以了,个人觉得问题还不是那么的大,提醒一下:1、配置虽然很重要,但是在绝大部分情况下都不是效率问题的罪魁祸首。2、mysql是一个数据库,对于数据库最重要考究的不应是效率,而是稳定性和数据准确性。

4、机器实在负荷不了

如果做了以上调整,服务器还是不能承受,那就只能通过架构级调整来优化了。

1、mysql同步。

通过mysql同步功能将数据同步到数台从数据库,由主数据库写入,从数据库提供读取。

我个人不是那么乐意使用mysql同步,因为这个办法会增加程序的复杂性,并常常会引起数据方面的错误。在高负荷的服务中,死机了还可以快速重启,但数据错误的话要恢复就比较麻烦。

2、加入缓存

加入缓存之后,就可以解决并发的问题,效果很明显。如果是实时系统,可以考虑用刷新缓存方式使缓存保持最新。

在前端加入squid的架构比较提倡使用,在命中率比较高的应用中,基本上可以解决问题。

如果是在程序逻辑层里面进行缓存,会增加很多复杂性,问题会比较多而且难解决,不建议在这一层面进行调整。

3、程序架构调整,支持同时连接多个数据库

如果web加入缓存后问题还是比较严重,只能通过程序架构调整,把应用拆散,用多台的机器同时提供服务。

如果拆散的话,对业务是有少许影响,如果业务当中有部分功能必须使用所有的数据,可以用一个完整库+n个分散库这样的架构,每次修改都在完整库和分散库各操作一次,或定期整理完整库。

当然,还有一种最笨的,把数据库整个完完整整的做拷贝,然后程序每次都把完整的sql在这些库执行一遍,访问时轮询访问,我认为这样要比mysql同步的方式安全。

4、使用 mysql proxy 代理

mysql proxy 可以通过代理把数据库中的各个表分散到数台服务器,但是它的问题是没有能解决热门表的问题,如果热门内容散在多个表中,用这个办法是比较轻松就能解决问题。

我没有用过这个软件也没有认真查过,不过我对它的功能有一点点怀疑,就是它怎么实现多个表之间的联合查询?如果能实现,那么效率如何呢?

5、使用memcachedb

数据库换用支持mysql的memcachedb,是可以一试的想法,从memcachedb的实现方式和层面来看对数据没有什么影响,不会对用户有什么困扰。

为我现在因为数据库方面问题不多,没有试验过这个玩意。不过,只要它支持mysql的大部分主要的语法,而且本身稳定,可用性是无需置疑的。

分享到:
评论

相关推荐

    MySQL性能调优与架构设计

    以下几点是调优和设计时需重点关注的: **2.1 理解Query处理流程** 深入理解MySQL如何处理SQL查询,是进行性能调优的基础。从解析、优化、执行计划生成到数据检索,每个步骤都有可能成为性能瓶颈。 **2.2 索引...

    MYSQL性能调优工具介绍与应用

    ### MySQL性能调优工具介绍与应用 MySQL作为全球最广泛使用的开源关系型数据库之一,在企业级应用中的地位不可动摇。为了确保MySQL能够高效稳定地运行,掌握一系列性能调优工具至关重要。本文将详细介绍多种MySQL...

    mysql 性能的检查和调优方法

    MySQL性能的检查与调优是数据库管理中的...总结,MySQL性能的检查和调优涉及多个层面,包括索引检查、SQL优化、配置调整以及硬件资源的评估。通过这些方法,可以有效地识别和解决性能瓶颈,提升MySQL数据库的运行效率。

    LINUX性能调优方法总结

    这份名为“LINUX性能调优方法总结”的文档,很可能包含了一系列关于如何优化Linux系统性能的技术和策略。以下是根据标题和描述可能涵盖的一些主要知识点: 1. **系统监控工具**:了解并使用如`top`, `htop`, `...

    MySQL性能调优与架构设计--全册

    MySQL是世界上最受欢迎的...本全册将详细讲解以上知识点,并通过实例演示如何在实际应用中实施这些策略,帮助读者成为MySQL性能调优与架构设计的专家。无论你是初学者还是有经验的DBA,都能从中获得宝贵的知识和经验。

    Mysql性能调优指南.docx

    通过检查 Mysql 状态参数,可以知道 Mysql 的当前状态和性能。 Mysql 索引实现原理分析 Mysql 索引是提高 Mysql 性能的关键。通过了解 Mysql 索引的实现原理,可以更好地优化 Mysql 的性能。 Mysql 配置优化参数...

    mysql性能调优讲解

    ### MySQL性能调优知识点 #### 一、MySQL性能调优概览 MySQL作为全球最受欢迎的开源数据库之一,在众多应用场景中发挥着重要作用。然而,随着数据量的增长和业务复杂度的提高,MySQL数据库可能会出现性能瓶颈,...

    mysql性能的检查和调优方法

    如果看到mysql消耗的cpu很大,可以用mysql的client工具来检查。在linux下执行/usr/local/mysql/bin/mysql-hlocalhost -uroot-p输入密码,如果没有密码,则不用-p参数就可以进到客户端界面中。看看当前的运行情况...

    mysql 性能调优 运维

    以上内容涵盖了MySQL性能调优和运维的多个方面,从基础概念到高级技术,每个知识点都值得深入学习和实践。作为一名DBA,理解和掌握这些知识,将有助于优化数据库性能,确保系统的高效稳定运行。

    mysqldumpslow等常用脚本 用于mysql和程序性能调优

    在本文中,我们将深入探讨`mysqldumpslow`以及与MySQL性能调优相关的其他重要脚本和策略。 `mysqldumpslow` 是MySQL客户端工具的一部分,它能够解析慢查询日志(slow query log),并以易于理解的格式显示统计信息...

    mysql数据库性能调优

    ### MySQL数据库性能调优 #### 引言 MySQL作为全球广泛使用的开源关系型数据库系统,在企业级应用和服务中扮演着重要角色...通过本文介绍的方法和技术,开发者和DBA可以更好地管理MySQL数据库,确保其稳定高效地运行。

    MySql数据库使用Sql调优

    本文将深入探讨MySQL的基本架构及其对SQL调优的影响,同时介绍两种性能监控方法。 首先,MySQL的基本架构包括连接器、查询缓存、分析器、优化器和执行器等几个关键部分。 1. **连接器**:负责与客户端建立连接,...

    MySQL DBA性能调优 全攻略

    ### MySQL DBA性能调优全攻略 #### 一、引言 在当今信息化时代,数据库作为数据管理和存储的核心工具,在企业应用中扮演着至关重要的角色...希望本文提供的指南能够帮助读者更好地理解和掌握MySQL性能调优的技术要点。

    MySQL管理之道 性能调优、高可用与监控.part2.rar

    3.1 影响mysql性能的因素 72 3.2 系统性能评估标准 73 3.2.1 影响linux服务器性能的因素 73 3.2.2 系统性能评估指标 74 3.2.3 开源监控和评估工具介绍 76 3.3 故障与处理 79 3.3.1 连接数过多导致程序连接...

    分析MySQL复制以及调优原理和方法

    MySQL复制和调优是数据库管理中的重要环节,它涉及到数据安全性、系统扩展性和高可用性。本文将深入探讨MySQL复制的原理、实现步骤...通过理解复制原理、掌握配置方法和调优技巧,我们可以更好地管理和维护MySQL集群。

    mysql 性能调优与架构设计 数据库Schema源码

    MySQL性能调优与架构设计是数据库管理中的关键领域,它涉及到如何优化查询速度、提高并发处理能力、确保数据安全和稳定性。在这个过程中,数据库Schema的设计起着至关重要的作用。Schema是数据库的蓝图,定义了...

Global site tag (gtag.js) - Google Analytics