有没有能翻译的软件翻译公司

MySQL数据库优化处理实现千万级快速分页分析,来看下吧。数据表 collect ( id, title ,info ,vtype) 就这4个字段,其中 title 用定长,info 用text, id 是逐渐,vtype是tinyint,vtype是索引。这是一个基本的新闻系统的简单模型。现在往里面填充数据,填充10万篇新闻。最后collect 为 10万条记录,数据库表占用硬盘1.6G。OK ,看下面这条sql语句:select id,title from collect limit 1000,10; 很快;基本上0.01秒就OK,再看下面的select id,title from collect limit 90000,10; 从9万条开始分页,结果?8-9秒完成,my god 哪出问题了????其实要优化这条数据,网上找得到答案。看下面一条语句:select id from collect order by id limit 90000,10; 很快,0.04秒就OK。 为什么?因为用了id主键做索引当然快。网上的改法是:select id,title from collect where id&=(select id from collect order by id limit 90000,1) limit 10;这就是用了id做索引的结果。可是问题复杂那么一点点,就完了。看下面的语句select id from collect where vtype=1 order by id limit 90000,10; 很慢,用了8-9秒!到了这里我相信很多人会和我一样,有崩溃感觉!vtype 做了索引了啊?怎么会慢呢?vtype做了索引是不错,你直接 select id from collect where vtype=1 limit 1000,10; 是很快的,基本上0.05秒,可是提高90倍,从9万开始,那就是0.05*90=4.5秒的速度了。和测试结果8-9秒到了一个数量级。从这里开始有人 提出了分表的思路,这个和discuz 论坛是一样的思路。思路如下:建一个索引表: t (id,title,vtype) 并设置成定长,然后做分页,分页出结果再到 collect 里面去找info 。 是否可行呢?实验下就知道了。10万条记录到 t(id,title,vtype) 里,数据表大小20M左右。用select id from t where vtype=1 order by id limit 90000,10; 很快了。基本上0.1-0.2秒可以跑完。为什么会这样呢?我猜想是因为collect 数据太多,所以分页要跑很长的路。limit 完全和数据表的大小有关的。其实这样做还是全表扫描,只是因为数据量小,只有10万才快。OK, 来个疯狂的实验,加到100万条,测试性能。加了10倍的数据,马上t表就到了200多M,而且是定长。还是刚才的查询语句,时间是0.1-0.2秒完成!分表性能没问题?错!因为我们的limit还是9万,所以快。给个大的,90万开始select id from t where vtype=1 order by id limit ; 看看结果,时间是1-2秒!why ?? 分表了时间还是这么长,非常之郁闷!有人说定长会提高limit的性能,开始我也以为,因为一条记录的长度是固定的,mysql 应该可以算出90万的位置才对啊? 可是我们高估了mysql 的智能,他不是商务数据库,事实证明定长和非定长对limit影响不大? 怪不得有人说 discuz到了100万条记录就会很慢,我相信这是真的,这个和数据库设计有关!难道MySQL 无法突破100万的限制吗???到了100万的分页就真的到了极限???答案是: NO !!!! 为什么突破不了100万是因为不会设计mysql造成的。下面介绍非分表法,来个疯狂的测试!一张表搞定100万记录,并且10G 数据库,如何快速分页!好了,我们的测试又回到 collect表,开始测试结论是: 30万数据,用分表法可行,超过30万他的速度会慢道你无法忍受!当然如果用分表+我这种方法,那是绝对完美的。但是用了我这种方法后,不用分表也可以完美解决!答案就是:复合索引! 有一次设计mysql索引的时候,无意中发现索引名字可以任取,可以选择几个字段进来,这有什么用呢?开始的select id from collect order by id limit 90000,10; 这么快就是因为走了索引,可是如果加了where 就不走索引了。抱着试试看的想法加了 search(vtype,id) 这样的索引。然后测试select id from collect where vtype=1 limit 90000,10; 非常快!0.04秒完成!再测试: select id ,title from collect where vtype=1 limit 90000,10; 非常遗憾,8-9秒,没走search索引!再测试:search(id,vtype),还是select id 这个语句,也非常遗憾,0.5秒。综上:如果对于有where 条件,又想走索引用limit的,必须设计一个索引,将where 放第一位,limit用到的主键放第2位,而且只能select 主键!完美解决了分页问题了。可以快速返回id就有希望优化limit , 按这样的逻辑,百万级的limit 应该在0.0x秒就可以分完。看来mysql 语句的优化和索引时非常重要的!好了,回到原题,如何将上面的研究成功快速应用于开发呢?如果用复合查询,我的轻量级框架就没的用了。分页字符串还得自己写,那多麻烦?这里再看一个例子,思路就出来了:select * from collect where id in (,7000); 竟然 0秒就可以查完!mygod ,mysql 的索引竟然对于in语句同样有效!看来网上说in无法用索引是错误的!有了这个结论,就可以很简单的应用于轻量级框架了:代码如下:$db=dblink();$db-&pagesize=20;$sql="select id from collect where vtype=$vtype";$db-&execute($sql);$strpage=$db-&strpage(); //将分页字符串保存在临时变量,方便输出while($rs=$db-&fetch_array()){$strid.=$rs['id'].',';}$strid=substr($strid,0,strlen($strid)-1); //构造出id字符串$db-&pagesize=0; //很关键,在不注销类的情况下,将分页清空,这样只需要用一次数据库连接,不需要再开;$db-&execute("select id,title,url,sTime,gTime,vtype,tag from collect where id in ($strid)");&?php while($rs=$db-&fetch_array()): ?&&tr&&td&&&?php echo $rs['id'];?&&/td&&td&&&?php echo $rs['url'];?&&/td&&td&&&?php echo $rs['sTime'];?&&/td&&td&&&?php echo $rs['gTime'];?&&/td&&td&&&?php echo $rs['vtype'];?&&/td&&td&&&a href="?act=show&id=&?php echo $rs['id'];?&" target="_blank"&&?php echo $rs['title'];?&&/a&&/td&&td&&&?php echo $rs['tag'];?&&/td&&/tr&&? ?&&/table&&?phpecho $通过简单的变换,其实思路很简单:1)通过优化索引,找出id,并拼成 "123," 这样的字符串。2)第2次查询找出结果。小小的索引+一点点的改动就使mysql 可以支持百万甚至千万级的高效分页!通过这里的例子,我反思了一点:对于大型系统,PHP千万不能用框架,尤其是那种连sql语句都看不到的框架!因为开始对于我的轻量级框架都差点崩 溃!只适合小型应用的快速开发,对于ERP,OA,大型网站,数据层包括逻辑层的东西都不能用框架。如果程序员失去了对sql语句的把控,那项目的风险将 会成几何级数增加!尤其是用mysql 的时候,mysql 一定需要专业的dba 才可以发挥他的最佳性能。一个索引所造成的性能差别可能是上千倍!PS: 经过实际测试,到了100万的数据,160万数据,15G表,190M索引,就算走索引,limit都得0.49秒。所以分页最好别让别人看到10万条以后的数据, 要不然会很慢!就算用索引。经过这样的优化,mysql到了百万级分页是个极限!但有这样的成绩已经很不错,如果你是用sqlserver肯定卡死!而 160万的数据用 id in (str) 很快,基本还是0秒。如果这样,千万级的数据,mysql应该也很容易应付。From:&2010年 总版技术专家分年内排行榜第二
2009年 总版技术专家分年内排行榜第三
匿名用户不能发表回复!|
每天回帖即可获得10分可用分!小技巧:
你还可以输入10000个字符
(Ctrl+Enter)
请遵守CSDN,不得违反国家法律法规。
转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。博客访问: 1259152
博文数量: 323
博客积分: 10653
博客等级: 上将
技术积分: 3198
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: Mysql/postgreSQL
目录一、优化概述二、查询与索引优化分析1性能瓶颈定位Show命令慢查询日志explain分析查询profiling分析查询&2索引及查询优化三、配置优化1) & & &max_connections2) & & &back_log3) & & &interactive_timeout4) & & &key_buffer_size5) & & &query_cache_size6) & & &record_buffer_size7) & & &read_rnd_buffer_size8) & & &sort_buffer_size9) & & &join_buffer_size10) & &table_cache11) & &max_heap_table_size12) & &tmp_table_size13) & &thread_cache_size14) & &thread_concurrency15) & &wait_timeout&一、&优化概述MySQL数据库是常见的两个瓶颈是CPU和I/O的瓶颈,CPU在饱和的时候一般发生在数据装入内存或从磁盘上读取数据时候。磁盘I/O瓶颈发生在装入数据远大于内存容量的时候,如果应用分布在网络上,那么查询量相当大的时候那么平瓶颈就会出现在网络上,我们可以用mpstat, iostat, sar和vmstat来查看系统的性能状态。除了服务器硬件的性能瓶颈,对于MySQL系统本身,我们可以使用工具来优化数据库的性能,通常有三种:使用索引,使用EXPLAIN分析查询以及调整MySQL的内部配置。二、查询与索引优化分析在优化MySQL时,通常需要对数据库进行分析,常见的分析手段有慢查询日志,EXPLAIN&分析查询,profiling分析以及show命令查询系统状态及系统变量,通过定位分析性能的瓶颈,才能更好的优化数据库系统的性能。1 性能瓶颈定位Show命令我们可以通过show命令查看MySQL状态及变量,找到系统的瓶颈:Mysql& show status ——显示状态信息(扩展show status like ‘XXX’)Mysql& show variables ——显示系统变量(扩展show variables like ‘XXX’)Mysql& show innodb status ——显示InnoDB存储引擎的状态Mysql& show processlist ——查看当前SQL执行,包括执行状态、是否锁表等Shell& mysqladmin variables -u username -p password——显示系统变量Shell& mysqladmin extended-status -u username -p password——显示状态信息查看状态变量及帮助:Shell& mysqld –verbose –help [|more #逐行显示]&比较全的Show命令的使用可参考: /a.cn/18/慢查询日志慢查询日志开启:在配置文件my.cnf或my.ini中在[d]一行下面加入两个配置参数log-slow-queries=/data/mysqldata/slow-query.log&&&&&&&&&&&long_query_time=2&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&注:log-slow-queries参数为慢查询日志存放的位置,一般这个目录要有mysql的运行帐号的可写权限,一般都将这个目录设置为mysql的数据存放目录;long_query_time=2中的2表示查询超过两秒才记录;在my.cnf或者my.ini中添加log-queries-not-using-indexes参数,表示记录下没有使用索引的查询。log-slow-queries=/data/mysqldata/slow-query.log&&&&&&&&&&&long_query_time=10&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&log-queries-not-using-indexes&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&慢查询日志开启方法二:我们可以通过命令行设置变量来即时启动慢日志查询。由下图可知慢日志没有打开,slow_launch_time=#&表示如果建立线程花费了比这个值更长的时间,slow_launch_threads 计数器将增加设置慢日志开启MySQL后可以查询long_query_time 的值 。&为了方便测试,可以将修改慢查询时间为5秒。慢查询分析mysqldumpslow我们可以通过打开log文件查看得知哪些SQL执行效率低下[root@localhost&mysql]#&more slow-query.log &&&&&&&&&&&&&&&&&&&&&&&&& &#&Time:&:46:34 &&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#&User@Host:&root[root]&@&localhost&[] &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&#&Query_time:&11&Lock_time:&0&Rows_sent:&1&Rows_examined:&6552961 &&&&&&&select&count(*)&from&t_&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&从日志中,可以发现查询时间超过5 秒的SQL,而小于5秒的没有出现在此日志中。如果慢查询日志中记录内容很多,可以使用mysqldumpslow工具(MySQL客户端安装自带)来对慢查询日志进行分类汇总。mysqldumpslow对日志文件进行了分类汇总,显示汇总后摘要结果。进入log的存放目录,运行[root@mysql_data]#mysqldumpslow &slow-query.log &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Reading&mysql&slow&query&log&from slow-query.log &&&&&&&&&&&&&&&&&&&&&&&&&&&Count:&2&Time=11.00s&(22s)&Lock=0.00s&(0s)&Rows=1.0&(2),&root[root]@mysql& &&select&count(N)&from&t_&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&mysqldumpslow命令/path/mysqldumpslow -s c -t 10 /database/mysql/slow-query.log&&&&&&&&&&&&&&&&&&&&&&这会输出记录次数最多的10条SQL语句,其中:-s, 是表示按照何种方式排序,c、t、l、r分别是按照记录次数、时间、查询时间、返回的记录数来排序,ac、at、al、ar,表示相应的倒叙;-t, 是top n的意思,即为返回前面多少条的数据;-g, 后边可以写一个正则匹配模式,大小写不敏感的;例如:/path/mysqldumpslow -s r -t 10 /database/mysql/slow-log&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&得到返回记录集最多的10个查询。/path/mysqldumpslow -s t -t 10 -g “left join” /database/mysql/slow-log&&&&&&&得到按照时间排序的前10条里面含有左连接的查询语句。使用mysqldumpslow命令可以非常明确的得到各种我们需要的查询语句,对MySQL查询语句的监控、分析、优化是MySQL优化非常重要的一步。开启慢查询日志后,由于日志记录操作,在一定程度上会占用CPU资源影响mysql的性能,但是可以阶段性开启来定位性能瓶颈。explain分析查询使用&EXPLAIN&关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。这可以帮你分析你的查询语句或是表结构的性能瓶颈。通过explain命令可以得到:– 表的读取顺序– 数据读取操作的操作类型– 哪些索引可以使用– 哪些索引被实际使用– 表之间的引用– 每张表有多少行被优化器查询EXPLAIN字段:ØTable:显示这一行的数据是关于哪张表的Øpossible_keys:显示可能应用在这张表中的索引。如果为空,没有可能的索引。可以为相关的域从WHERE语句中选择一个合适的语句Økey:实际使用的索引。如果为NULL,则没有使用索引。MYSQL很少会选择优化不足的索引,此时可以在SELECT语句中使用USE INDEX(index)来强制使用一个索引或者用IGNORE INDEX(index)来强制忽略索引Økey_len:使用的索引的长度。在不损失精确性的情况下,长度越短越好Øref:显示索引的哪一列被使用了,如果可能的话,是一个常数Ørows:MySQL认为必须检索的用来返回请求数据的行数Øtype:这是最重要的字段之一,显示查询使用了何种类型。从最好到最差的连接类型为system、const、eq_reg、ref、range、index和ALLnsystem、const:可以将查询的变量转为常量.&&如id=1; id为 主键或唯一键.neq_ref:访问索引,返回某单一行的数据.(通常在联接时出现,查询使用的索引为主键或惟一键)nref:访问索引,返回某个值的数据.(可以返回多行) 通常使用=时发生nrange:这个连接类型使用索引返回一个范围中的行,比如使用&或&查找东西,并且该字段上建有索引时发生的情况(注:不一定好于index)nindex:以索引的顺序进行全表扫描,优点是不用排序,缺点是还要全表扫描nALL:全表扫描,应该尽量避免ØExtra:关于MYSQL如何解析查询的额外信息,主要有以下几种nusing index:只用到索引,可以避免访问表.&nusing where:使用到where来过虑数据. 不是所有的where clause都要显示using where. 如以=方式访问索引.nusing tmporary:用到临时表nusing filesort:用到额外的排序. (当使用order by v1,而没用到索引时,就会使用额外的排序)nrange checked for eache record(index map:N):没有好的索引.&profiling分析查询通过慢日志查询可以知道哪些SQL语句执行效率低下,通过explain我们可以得知SQL语句的具体执行情况,索引使用等,还可以结合show命令查看执行状态。如果觉得explain的信息不够详细,可以同通过profiling命令得到更准确的SQL执行消耗系统资源的信息。profiling默认是关闭的。可以通过以下语句查看&&打开功能: mysql&set profiling=1; 执行需要测试的sql 语句:mysql& show profiles\G; 可以得到被执行的SQL语句的时间和IDmysql&show profile for query 1; 得到对应SQL语句执行的详细信息Show Profile命令格式:SHOW PROFILE [type [, type] … ]&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&&&& [FOR QUERY n]&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& [LIMIT row_count [OFFSET offset]]&&&&&&&&&&&&&&& &&&&&&&&&&&&&type:&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& ALL&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&& | BLOCK IO&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | CONTEXT SWITCHES&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | CPU&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | IPC&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | MEMORY&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | PAGE FAULTS&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | SOURCE&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&& &&&&&&& | SWAPS&&&&&&&&&&&&&&&&&&&&以上的16rows是针对非常简单的select语句的资源信息,对于较复杂的SQL语句,会有更多的行和字段,比如converting HEAP to MyISAM&、Copying to tmp table等等,由于以上的SQL语句不存在复杂的表操作,所以未显示这些字段。通过profiling资源耗费信息,我们可以采取针对性的优化措施。&测试完毕以后 ,关闭参数:mysql& set profiling=0&&2&&&& 索引及查询优化&索引的类型Ø&普通索引:这是最基本的索引类型,没唯一性之类的限制。Ø&唯一性索引:和普通索引基本相同,但所有的索引列值保持唯一性。Ø&主键:主键是一种唯一索引,但必须指定为”PRIMARY KEY”。Ø&全文索引:MYSQL从3.23.23开始支持全文索引和全文检索。在MYSQL中,全文索引的索引类型为FULLTEXT。全文索引可以在VARCHAR或者TEXT类型的列上创建。大多数MySQL索引(PRIMARY KEY、UNIQUE、INDEX和FULLTEXT)使用B树中存储。空间列类型的索引使用R-树,MEMORY表支持hash索引。单列索引和多列索引(复合索引)索引可以是单列索引,也可以是多列索引。对相关的列使用索引是提高SELECT操作性能的最佳途径之一。多列索引:MySQL可以为多个列创建索引。一个索引可以包括15个列。对于某些列类型,可以索引列的左前缀,列的顺序非常重要。多列索引可以视为包含通过连接索引列的值而创建的值的排序的数组。一般来说,即使是限制最严格的单列索引,它的限制能力也远远低于多列索引。最左前缀多列索引有一个特点,即最左前缀(Leftmost Prefixing)。假如有一个多列索引为key(firstname lastname age),当搜索条件是以下各种列的组合和顺序时,MySQL将使用该多列索引:firstname,lastname,agefirstname,lastnamefirstname也就是说,相当于还建立了key(firstname lastname)和key(firstname)。索引主要用于下面的操作:Ø&快速找出匹配一个WHERE子句的行。Ø&删除行。当执行联接时,从其它表检索行。Ø&对具体有索引的列key_col找出MAX()或MIN()值。由预处理器进行优化,检查是否对索引中在key_col之前发生所有关键字元素使用了WHERE&key_part_#&=&constant。在这种情况下,MySQL为每个MIN()或MAX()表达式执行一次关键字查找,并用常数替换它。如果所有表达式替换为常量,查询立即返回。例如:SELECT MIN(key2), MAX (key2)&&FROM&tb&WHERE&key1=10;Ø&如果对一个可用关键字的最左面的前缀进行了排序或分组(例如,ORDER BY key_part_1,key_part_2),排序或分组一个表。如果所有关键字元素后面有DESC,关键字以倒序被读取。Ø&在一些情况中,可以对一个查询进行优化以便不用查询数据行即可以检索值。如果查询只使用来自某个表的数字型并且构成某些关键字的最左面前缀的列,为了更快,可以从索引树检索出值。SELECT&key_part3&FROM&tb&WHERE&key_part1=1有时MySQL不使用索引,即使有可用的索引。一种情形是当优化器估计到使用索引将需要MySQL访问表中的大部分行时。(在这种情况下,表扫描可能会更快些)。然而,如果此类查询使用LIMIT只搜索部分行,MySQL则使用索引,因为它可以更快地找到几行并在结果中返回。例如:&合理的建立索引的建议:(1)& 越小的数据类型通常更好:越小的数据类型通常在磁盘、内存和CPU缓存中都需要更少的空间,处理起来更快。&(2)& 简单的数据类型更好:整型数据比起字符,处理开销更小,因为字符串的比较更复杂。在MySQL中,应该用内置的日期和时间数据类型,而不是用字符串来存储时间;以及用整型数据类型存储IP地址。(3)& 尽量避免NULL:应该指定列为NOT NULL,除非你想存储NULL。在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值&这部分是关于索引和写SQL语句时应当注意的一些琐碎建议和注意点。1.&当结果集只有一行数据时使用LIMIT 12.&避免SELECT *,始终指定你需要的列从表中读取越多的数据,查询会变得更慢。他增加了磁盘需要操作的时间,还是在数据库服务器与WEB服务器是独立分开的情况下。你将会经历非常漫长的网络延迟,仅仅是因为数据不必要的在服务器之间传输。3.&使用连接(JOIN)来代替子查询(Sub-Queries)&&&&&& 连接(JOIN).. 之所以更有效率一些,是因为MySQL不需要在内存中创建临时表来完成这个逻辑上的需要两个步骤的查询工作。4.&使用ENUM、CHAR&而不是VARCHAR,使用合理的字段属性长度5.&尽可能的使用NOT NULL6.&固定长度的表会更快7.&拆分大的DELETE&或INSERT&语句8.&查询的列越小越快&&Where条件在查询中,WHERE条件也是一个比较重要的因素,尽量少并且是合理的where条件是很重要的,尽量在多个条件的时候,把会提取尽量少数据量的条件放在前面,减少后一个where条件的查询时间。有些where条件会导致索引无效:Ø&where子句的查询条件里有!=,MySQL将无法使用索引。Ø&where子句使用了Mysql函数的时候,索引将无效,比如:select * from tb where left(name, 4) = ‘xxx’Ø&使用LIKE进行搜索匹配的时候,这样索引是有效的:select * from tbl1 where name like ‘xxx%’,而like ‘%xxx%’ 时索引无效&三、&&&&配置优化安装MySQL后,配置文件my.cnf在 /MySQL安装目录/share/mysql目录中,该目录中还包含多个配置文件可供参考,有f ,f, &f,f,分别对应大中小型数据库应用的配置。win环境下即存在于MySQL安装目录中的.ini文件。&下面列出了对性能优化影响较大的主要变量,主要分为连接请求的变量和缓冲区变量。1.&&&连接请求的变量:1)&&&& max_connectionsMySQL的最大连接数,增加该值增加mysqld 要求的文件描述符的数量。如果服务器的并发连接请求量比较大,建议调高此值,以增加并行连接数量,当然这建立在机器能支撑的情况下,因为如果连接数越多,介于MySQL会为每个连接提供连接缓冲区,就会开销越多的内存,所以要适当调整该值,不能盲目提高设值。数值过小会经常出现ERROR 1040: Too many connections错误,可以过’conn%’通配符查看当前状态的连接数量,以定夺该值的大小。show variables like ‘max_connections’ 最大连接数show& status like ‘max_used_connections’响应的连接数如下:mysql& show variables like ‘max_connections‘;+———————–+——-+| Variable_name | Value |+———————–+——-+| max_connections | 256  |+———————–+——-+mysql& show status like ‘max%connections‘;+———————–+——-+| Variable_name &&&&& | Value |+—————————-+——-+| max_used_connections | 256|+—————————-+——-+max_used_connections / max_connections * 100% (理想值≈ 85%)&如果max_used_connections跟max_connections相同 那么就是max_connections设置过低或者超过服务器负载上限了,低于10%则设置过大。2)&&&& back_logMySQL能暂存的连接数量。当主要MySQL线程在一个很短时间内得到非常多的连接请求,这就起作用。如果MySQL的连接数据达到max_connections时,新来的请求将会被存在堆栈中,以等待某一连接释放资源,该堆栈的数量即back_log,如果等待连接的数量超过back_log,将不被授予连接资源。back_log值指出在MySQL暂时停止回答新请求之前的短时间内有多少个请求可以被存在堆栈中。只有如果期望在一个短时间内有很多连接,你需要增加它,换句话说,这值对到来的TCP/IP连接的侦听队列的大小。当观察你主机进程列表(mysql& show full processlist),发现大量264084 | unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时,就要加大back_log 的值了。默认数值是50,可调优为128,对于系统设置范围为小于512的整数。&3)&&&& interactive_timeout一个交互连接在被服务器在关闭前等待行动的秒数。一个交互的客户被定义为对mysql_real_connect()使用CLIENT_INTERACTIVE 选项的客户。&默认数值是28800,可调优为7200。&2.&&&缓冲区变量全局缓冲:4)&&&& key_buffer_sizekey_buffer_size指定索引缓冲区的大小,它决定索引处理的速度,尤其是索引读的速度。通过检查状态值Key_read_requests和Key_reads,可以知道key_buffer_size设置是否合理。比例key_reads / key_read_requests应该尽可能的低,至少是1:100,1:1000更好(上述状态值可以使用SHOW STATUS LIKE ‘key_read%’获得)。key_buffer_size只对MyISAM表起作用。即使你不使用MyISAM表,但是内部的临时磁盘表是MyISAM表,也要使用该值。可以使用检查状态值created_tmp_disk_tables得知详情。举例如下:mysql& show variables like ‘key_buffer_size‘;+——————-+————+| Variable_name | Value&&&&& |+———————+————+| key_buffer_size |
|+———— ———-+————+key_buffer_size为512MB,我们再看一下key_buffer_size的使用情况:mysql& show global status like ‘key_read%‘;+————————+————-+| Variable_name & | Value&& &|+————————+————-+| Key_read_requests|
|| Key_reads   | &6798830 & &&&|+————————+————-+一共有个索引读取请求,有6798830个请求在内存中没有找到直接从硬盘读取索引,计算索引未命中缓存的概率:key_cache_miss_rate =Key_reads / Key_read_requests * 100%,设置在1/1000左右较好默认配置数值是M),主机有4GB内存,可以调优值为6MB)。5)&&&& query_cache_size使用查询缓冲,MySQL将查询结果存放在缓冲区中,今后对于同样的SELECT语句(区分大小写),将直接从缓冲区中读取结果。通过检查状态值Qcache_*,可以知道query_cache_size设置是否合理(上述状态值可以使用SHOW STATUS LIKE ‘Qcache%’获得)。如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲不够的情况,如果Qcache_hits的值也非常大,则表明查询缓冲使用非常频繁,此时需要增加缓冲大小;如果Qcache_hits的值不大,则表明你的查询重复率很低,这种情况下使用查询缓冲反而会影响效率,那么可以考虑不用查询缓冲。此外,在SELECT语句中加入SQL_NO_CACHE可以明确表示不使用查询缓冲。&与查询缓冲有关的参数还有query_cache_type、query_cache_limit、query_cache_min_res_unit。&query_cache_type指定是否使用查询缓冲,可以设置为0、1、2,该变量是SESSION级的变量。query_cache_limit指定单个查询能够使用的缓冲区大小,缺省为1M。query_cache_min_res_unit是在4.1版本以后引入的,它指定分配缓冲区空间的最小单位,缺省为4K。检查状态值Qcache_free_blocks,如果该值非常大,则表明缓冲区中碎片很多,这就表明查询结果都比较小,此时需要减小query_cache_min_res_unit。举例如下:mysql& show global status like ‘qcache%‘;+——————————-+—————–+| Variable_name&&&&&&&&&&&&&&&&& | Value &&&&&& |+——————————-+—————–+| Qcache_free_blocks &&&&&& | 22756 &&&&& || Qcache_free_memory &&& | &&& || Qcache_hits     &&&&& |
|| Qcache_inserts    &&&& | && || Qcache_lowmem_prunes&& | 4010916&&&&& || Qcache_not_cached | &&& || Qcache_queries_in_cache | 43560 || Qcache_total_blocks&&&&&&&&& | 111212 &&&& |+——————————-+—————–+mysql& show variables like ‘query_cache%‘;+————————————–+————–+| Variable_name     & &&&& | Value &&&& |+————————————–+———–+| query_cache_limit     &&& | 2097152 &&& || query_cache_min_res_unit &&&& | 4096  & || query_cache_size     &&& |
|| query_cache_type     && | ON & &&&&&&& || query_cache_wlock_invalidate | OFF & |+————————————–+—————+查询缓存碎片率= Qcache_free_blocks / Qcache_total_blocks * 100%如果查询缓存碎片率超过20%,可以用FLUSH QUERY CACHE整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话。查询缓存利用率= (query_cache_size – Qcache_free_memory) / query_cache_size * 100%查询缓存利用率在25%以下的话说明query_cache_size设置的过大,可适当减小;查询缓存利用率在80%以上而且Qcache_lowmem_prunes & 50的话说明query_cache_size可能有点小,要不就是碎片太多。查询缓存命中率= (Qcache_hits – Qcache_inserts) / Qcache_hits * 100%示例服务器查询缓存碎片率=20.46%,查询缓存利用率=62.26%,查询缓存命中率=1.94%,命中率很差,可能写操作比较频繁吧,而且可能有些碎片。每个连接的缓冲6)&&&&record_buffer_size每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。默认数值是K),可改为M)7)&&&& read_rnd_buffer_size随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySQL会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySQL会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开销过大。一般可设置为16M&8)&&&& sort_buffer_size每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速ORDER BY或GROUP BY操作。默认数值是M),可改为M)。9)&&&& join_buffer_size联合查询操作所能使用的缓冲区大小record_buffer_size,read_rnd_buffer_size,sort_buffer_size,join_buffer_size为每个线程独占,也就是说,如果有100个线程连接,则占用为16M*10010)& table_cache表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_cache的值。如果你发现open_tables等于table_cache,并且opened_tables在不断增长,那么你就需要增加table_cache的值了(上述状态值可以使用SHOW STATUS LIKE ‘Open%tables’获得)。注意,不能盲目地把table_cache设置成很大的值。如果设置得太高,可能会造成文件描述符不足,从而造成性能不稳定或者连接失败。1G内存机器,推荐值是128-256。内存在4GB左右的服务器该参数可设置为256M或384M。11)& max_heap_table_size用户可以创建的内存表(memory table)的大小。这个值用来计算内存表的最大行数值。这个变量支持动态改变,即set @max_heap_table_size=#这个变量和tmp_table_size一起限制了内部内存表的大小。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自动将内存中的heap表改为基于硬盘的MyISAM表。12)& tmp_table_size通过设置tmp_table_size选项来增加一张临时表的大小,例如做高级GROUP BY操作生成的临时表。如果调高该值,MySQL同时将增加heap表的大小,可达到提高联接查询速度的效果,建议尽量优化查询,要确保查询过程中生成的临时表在内存中,避免临时表过大导致生成基于硬盘的MyISAM表。mysql& show global status like ‘created_tmp%‘;+——————————–+———+| Variable_name  &&&&&&&&&& | Value |+———————————-+———+| Created_tmp_disk_tables | 21197& || Created_tmp_files   | 58  || Created_tmp_tables  | 1771587 |+——————————–+———–+每次创建临时表,Created_tmp_tables增加,如果临时表大小超过tmp_table_size,则是在磁盘上创建临时表,Created_tmp_disk_tables也增加,Created_tmp_files表示MySQL服务创建的临时文件文件数,比较理想的配置是:Created_tmp_disk_tables / Created_tmp_tables * 100% &= 25%比如上面的服务器Created_tmp_disk_tables / Created_tmp_tables * 100% =1.20%,应该相当好了默认为16M,可调到64-256最佳,线程独占,太大可能内存不够I/O堵塞13)&&thread_cache_size可以复用的保存在中的线程的数量。如果有,新的线程从缓存中取得,当断开连接的时候如果有空间,客户的线置在缓存中。如果有很多新的线程,为了提高性能可以这个变量值。通过比较 Connections和Threads_created状态的变量,可以看到这个变量的作用。默认值为110,可调优为80。&14)& thread_concurrency推荐设置为服务器&CPU核数的2倍,例如双核的CPU, 那么thread_concurrency的应该为4;2个双核的cpu,&thread_concurrency的值应为8。默认为815)& wait_timeout指定一个请求的最大连接时间,对于4GB左右内存的服务器可以设置为5-10。&3.&&&&配置InnoDB的几个变量innodb_buffer_pool_size对于InnoDB表来说,innodb_buffer_pool_size的作用就相当于key_buffer_size对于MyISAM表的作用一样。InnoDB使用该参数指定大小的内存来缓冲数据和索引。对于单独的MySQL服务器,最大可以把该值设置成物理内存的80%。根据MySQL手册,对于2G内存的机器,推荐值是1G(50%)。&innodb_flush_log_at_trx_commit主要控制了innodb将log buffer中的数据写入日志文件并flush磁盘的时间点,取值分别为0、1、2三个。0,表示当事务提交时,不做日志写入操作,而是每秒钟将log buffer中的数据写入日志文件并flush磁盘一次;1,则在每秒钟或是每次事物的提交都会引起日志文件写入、flush磁盘的操作,确保了事务的ACID;设置为2,每次事务提交引起写入日志文件的动作,但每秒钟完成一次flush磁盘操作。实际测试发现,该值对插入数据的速度影响非常大,设置为2时插入10000条记录只需要2秒,设置为0时只需要1秒,而设置为1时则需要229秒。因此,MySQL手册也建议尽量将插入操作合并成一个事务,这样可以大幅提高速度。根据MySQL手册,在允许丢失最近部分事务的危险的前提下,可以把该值设为0或2。&innodb_log_buffer_sizelog缓存大小,一般为1-8M,默认为1M,对于较大的事务,可以增大缓存大小。可设置为4M或8M。&innodb_additional_mem_pool_size该参数指定InnoDB用来存储数据字典和其他内部数据结构的内存池大小。缺省值是1M。通常不用太大,只要够用就行,应该与表结构的复杂度有关系。如果不够用,MySQL会在错误日志中写入一条警告信息。根据MySQL手册,对于2G内存的机器,推荐值是20M,可适当增加。&innodb_thread_concurrency=8推荐设置为&2*(NumCPUs+NumDisks),默认一般为8
阅读(33919) | 评论(0) | 转发(4) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。}

我要回帖

更多关于 软件翻译公司 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信