Mysql**库性能优化一

时间:2016.04.20 发布人:cb8505

Mysql**库性能优化一

已解决问题

谷歌cb8505用户在2016.04.20提交了关于“后天Mysql**库性能优化一”的提问,欢迎大家涌跃发表自己的观点。目前共有1个回答,最后更新于2024-08-18T18:07:47。希望大家能够帮助她。

详细问题描述及疑问:期待您的答案,希望你能感受到,我最真诚的谢意 !

希望以下的回答,能够帮助你。

第1个回答

用户名:yangjuming  

今天,**库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显。关于**库的性能,这并不只是DBA才需要担心的事,而这更是我们程序员需要去关注的事情。当我们去设计数来自据库表结构,对操作**库时(尤其是查表时的SQL语句),我们都需要注意**操作的性能。这里,我们不会讲过多的SQL语句的优化,而只是针对MySQL这一We问答b应用最多的**库。

mysql的性能优化无法一蹴高而就,必须一步一步慢慢来,从各个方面进行优化,最终性能就会有大的提升。

Mysql**库的优化苗化布齐技术

对mysql优化是一个综合性的技术,主要包括

•表的设计合理化(符合3里世慢诉历危罗圆够罗NF)

•添加适当索引(index)[四种:普通索引、主键索引、果等海审更向支举路唯一索引unique、全文索引]

•分表技术(水平分割、垂直分割)

•读写[写:update/delete/add]分离

•存储过程[模块取液跑房术须化编程,可以提高速度]

•对mysql配置优化[配置最大并发数my.ini,调整缓存大小]

•mysql服务器硬件升级

•定映映正例初时的去**不需要的**,定时进行碎片整理(MyISAM)

**库优化工作

对于一个以**为中心的应用,时**库的好坏直接影响到程序的性能,因此**库性能至关重要。一般来说,要保**库的效率,要做好以下四个方面的工作:

①**库设计

②sql语句优化

③**库参数配置

④恰当的硬件资源和操作系统

此外,使用适当的存储过程,也能提升性能。

这个顺序也表现了这四个工作对性能影响的大小

**库表设计

通俗地理解三个范式,对于**库设计大有好处。在**库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通

俗地理解驶用的理解,并不是最科学最准确的理解):

第一范式:1NF是对属性的**性约束,要求属性少还歌岁况光(列)具有**性,不可再分解;(只要守系型**库都满足1NF)

第二范式:2NF是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性;

第三范式:3NF是对字段冗余性的约束,它封要求字段没有冗余。没有冗余的**库设计可以做到。

但是,没有冗余的**库未必是最好的**库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余**。具体做法是:在概念**模型设计时遵守进孔选任怕大第三范式,降低范式标准的工作放到物理**模型设计时考虑。降低范式就是增加字段,允许冗余。

☞**库的分类

关系型**库:mysql/oracle/db2/informix/sysbas带岩饭失剧e/sqlserver

坟系型**库:(特点:面向对象或者集合)

NoSql**库:MongoDB(特点是面向文档)

举例说明什么是适度冗余,或者说有理由的冗余!


上面洲映处限衡阿谓落者略石这个就是不合适的冗余,原因是:

在这里,为了提高学生活动记录的检索效率,调此损能把单位名称冗余到学生活动记录表里。单位信息有500条记录,而学生活动记录在

一年内大概有200万**量。如果学生活动记设施镇录表不冗余这个单位名称字段,只包含三个int字段和一个timestamp字段,只占用了16字节,是一个很小的表。谈自毛牛回重而冗余了一个varchar(32)的字段后则是原来的3倍,检索起来相应也多了这么多的I/O。而且记录数相差悬殊,500VS2000000,导致更新一个单位名称还要更新4000条冗余记录。由此可见,这个冗余根本就是适得其反。

订单表里面的Price就是一个冗余字段,因为我们可以从订单明细表中统计出这个订单的价格,但是这个冗余是合理的,也能提升查询性能。

从上面两个例子中可以得出一个光审半论结论:

1---n冗余应当发补图生在1这一方.

SQL语句优化

SQL优化察试的一般步骤

1.通过showstatus命令了解各种SQL的执行频率。

2.**执行效率较低的SQL语句-(重点select)

3.通过explain分析低效率的SQL

4.确定问题并采取相应的优化措施

--select语句分类SelectDml**操作语言(insertupdatedelete)dtl**事物语言(commitrollbacks**epoint)Ddl**定义语言(createalterdrop..)Dcl(**控制语言)grantrevoke--Showstatus常用命令--查询本次会话Showsessionstatuslike'com_%';//showsessionstatuslike'Com_select'--查询全局Showglobalstatuslike'com_%';--给某个用户授权grantallprivilegeson*.*to'abc'@'%';--为什么这样授权'abc'表示用户名'@'表示host,查看一下mysql->user表就知道了--回收权限revokeallon*.*from'abc'@'%';--刷新权限[也可以不写]flushprivileges;

SQL语句优化-show参数

MySQL客户端连接成功后,通过使用show[session|global]status命令可以提供服务器状态信息。其中的session来表示当前的连接的统计结果,global来表示自**库上次启动至今的统计结果。默认是session级别的。

下面的例子:

showstatuslike'Com_%';

其中Com_XXX表示XXX语句所执行的次数。

重点注意:Com_select,Com_insert,Com_update,Com_delete通过这几个参数,可以容易地了解到当前**库的应用是以插入更新为主还是以查询操作为主,以及各类的SQL大致的执行比例是多少。

还有几个常用的参数便于用户了解**库的基本情况。

Connections:试图连接MySQL服务器的次数

Uptime:服务器工作的时间(单位秒)

Slow_queries:慢查询的次数(默认是慢查询时间10s)

showstatuslike'Connections'showstatuslike'Uptime'showstatuslike'Slow_queries'

如何查询mysql的慢查询时间

Showvariableslike'long_query_time';

修改mysql慢查询时间

setlong_query_time=2

SQL语句优化-**慢查询

问题是:如何从一个大项目中,迅速的**执行速度慢的语句.(**慢查询)

首先我们了解mysql**库的一些运行状态如何查询(比如想知道当前mysql运行的时间/一**执行了多少次

select/update/delete../当前连接)

为了便于测试,我霉建一个大表(400万)->使用存储过程构建

默认情况下,mysql认为10秒才是一个慢查询.

修改mysql的慢查询.

showvariableslike'long_query_time';//可以显示当前慢查询时间setlong_query_time=1;//可以修改慢查询时间

构建大表->大表中记录有要求,记录是不同才有用,否则测试效果和真实的相差大.创建:

CREATETABLEdept(/*部门表*/deptnoMEDIUMINTUNSIGNEDNOT**LLDEFAULT0,/*编号*/dnameVARCh**AR(20)NOT**LLDEFAULT"",/*名称*/locVARCh**AR(13)NOT**LLDEFAULT""/*地点*/)ENGINE=MyISAMDEFAULTCh**AR**T=utf8;CREATETABLEemp(empnoMEDIUMINTUNSIGNEDNOT**LLDEFAULT0,/*编号*/enameVARCh**AR(20)NOT**LLDEFAULT"",/*名字*/jobVARCh**AR(9)NOT**LLDEFAULT"",/*工作*/mgrMEDIUMINTUNSIGNEDNOT**LLDEFAULT0,/*上级编号*/hiredateDATENOT**LL,/*入职时间*/salDECIMAL(7,2)NOT**LL,/*薪水*/commDECIMAL(7,2)NOT**LL,/*红利*/deptnoMEDIUMINTUNSIGNEDNOT**LLDEFAULT0/*部门编号*/)ENGINE=MyISAMDEFAULTCh**AR**T=utf8;CREATETABLEsalgrade(gradeMEDIUMINTUNSIGNEDNOT**LLDEFAULT0,losalDECIMAL(17,2)NOT**LL,hisalDECIMAL(17,2)NOT**LL)ENGINE=MyISAMDEFAULTCh**AR**T=utf8;

测试**

IN**RTINTOsalgradeVALUES(1,700,1200);IN**RTINTOsalgradeVALUES(2,1201,1400);IN**RTINTOsalgradeVALUES(3,1401,2000);IN**RTINTOsalgradeVALUES(4,2001,3000);IN**RTINTOsalgradeVALUES(5,3001,9999);

为了存储过程能够正常执行,我们需要把命令执行结束符修改delimiter$$
创建函数,该函数会返回一个指定长度的随机字符串

createfunctionrand_string(nINT)returnsvarchar(255)#该函数会返回一个字符串begin#chars_str定义一个变量chars_str,类型是varchar(100),默认值'abcdefghijklmnopqrstuvwxyzABCDEFJh**IJKLMNOPQRSTUVWXYZ';declarechars_strvarchar(100)default'abcdefghijklmnopqrstuvwxyzABCDEFJh**IJKLMNOPQRSTUVWXYZ';declarereturn_strvarchar(255)default'';declareiintdefault0;whilei<ndosetreturn_str=concat(return_str,substring(chars_str,floor(1+rand()*52),1));seti=i+1;endwhile;returnreturn_str;end

创建一个存储过程

createproce**reinsert_emp(instartint(10),inmax_**mint(10))begindeclareiintdefault0;#setautocommit=0把autocommit设置成0setautocommit=0;repeatseti=i+1;insertintoempvalues((start+i),rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand());untili=max_**mendrepeat;commit;end#调用刚刚写好的函数,1800000条记录,从100001号开始callinsert_emp(100001,4000000);

这时我们如果出现一条语句执行时间超过1秒中,就会统计到.

如果把慢查询的sql记录到我们的一个日志中

在默认情况下,低版本的mysql不会记录慢查询,需要在启动mysql时候,指定记录慢查询才可以

bin\mysqld.exe--safe-mode--slow-query-log[mysql5.5可以在my.ini指定]

bin\mysqld.exe–log-slow-queries=d:/abc.log[低版本mysql5.0可以在my.ini指定]

该慢查询日志会放在data目录下[在mysql5.0这个版本中时放在mysql安装目录/data/下],在mysql5.5.19下是需要查看

my.ini的datadir="C:/DocumentsandSettings/AllUsers/ApplicationData/MySQL/MySQLServer5.5/Data/“来确定.

在mysql5.6中,默认是启动记录慢查询的,my.ini的所在目录为:C:\ProgramData\MySQL\MySQLServer5.6,其中有一个配置项

slow-query-log=1

针对mysql5.5启动慢查询有两种方法

bin\mysqld.exe--safe-mode--slow-query-log

也可以在my.ini文件中配置:

[mysqld]#TheTCP/IPPorttheMySQLServerwilllistenonport=3306slow-query-log

通过慢查询日志**执行效率较低的SQL语句。慢查询日志记录了所有执行时间超过long_query_time所设置的SQL语句。

showvariableslike'long_query_time';setlong_query_time=2;

为dept表添加**

descdept;ALTERtabledeptaddidintPRIMARYkeyauto_increment;CREATEPRIMARYKEYondept(id);createINDEXidx_dptno_dptnameondept(deptno,dname);IN**RTintodept(deptno,dname,loc)values(1,'研发部','康和盛大厦5楼501');IN**RTintodept(deptno,dname,loc)values(2,'**品部','康和盛大厦5楼502');IN**RTintodept(deptno,dname,loc)values(3,'财务部','康和盛大厦5楼503');UPDATEempsetdeptno=1whereempno=100002;

****测试语句***[对emp表的记录可以为0000,效果很明显慢]

select*fromempwhereempno=(selectempnofromempwhereename='研发部')

如果带上orderbye.empno速度就会更慢,有时会到1min多.

测试语句

select*fromempe,deptdwheree.empno=100002ande.deptno=d.deptno;

查看慢查询日志:默认为**目录data中的host-name-slow.log。低版本的mysql需要通过在开启mysql时使用--log-slow-queries[=file_name]来配置

SQL语句优化-explain分析问题

Explainselect*fromempwhereename=“wsrcla”

会**生如下信息:

select_type:表示查询的类型。

table:输出结果集的表

type:表示表的连接类型

possible_keys:表示查询时,可能使用的索引

key:表示实际使用的索引

key_len:索引字段的长度

rows:扫描出的行数(估算的行数)

Extra:执行情况的描述和说明

explainselect*fromempwhereename='JKLOIP'

如果要测试Extra的filesort可以对上面的语句修改

explainselect*fromemporderbyename\G

EXPLAIN详解

id

**LECT识别符。这是**LECT的查询序列号

id示例

**LECT*FROMempWh**EREempno=1andename=(**LECTenameFROMempWh**EREempno=100001)\G;

select_type

PRIMARY:子查询中最外层查询

SUBQUERY:子查询内层第一个**LECT,结果不依赖于外部查询

DEPENDENTSUBQUERY:子查询内层第一个**LECT,依赖于外部查询

UNION:UNION语句中第二个**LECT开始后面所有**LECT,

SIMPLE

UNIONRESULTUNION中合并结果

Table

显示这一步所访问**库中表名称

Type

对表访问方式

ALL:

**LECT*FROMemp\G

完整的表扫描通常不好

**LECT*FROM(**LECT*FROMempWh**EREempno=1)a;

system:表仅有一行(=系统表)。这是const联接类型的一个特

const:表最多有一个匹配行

Possible_keys

该查询可以利用的索引,如果没有任何索引显示**ll

Key

Mysql从Possible_keys所选择使用索引

Rows

估算出结果集行数

Extra

查询细节信息

Notables:Query语句中使用FROMDUAL或不含任何FROM子句

Usingfilesort:当Query中包含ORDERBY操作,而且无法利用索引完成排序,

ImpossibleWh**EREnoticedafterreadingconsttables:MYSQLQueryOptimizer

通过收集统计信息不可能存在结果

Usingtemporary:某些操作必须使用临时表,常见GROUPBY;ORDERBY

Usingwhere:不用读取表中所有信息,仅通过索引就可以获取所需**;

以上所述是小编给大家介绍的Mysql**库性能优化一,下篇文章继续给大家介绍mysql**库性能优化二,希望大家持续关注本站最新内容!