Mysql数据库的优化(本文摘自于网络,文章末端有原文链接)

对于一个以数据为中心的应用,数据库的好坏直接影响到程序的性能,因此数据库性能至关重要。一

般来说,要保证数据库的效率,要做好以下四个方面的工作:

① 数据库设计

② sql语句优化

③ 数据库参数配置

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

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

1.

通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通俗地理解是够用的理解,并不是最科学最准确的理解):

第一范式:1NF是对属性的原子性约束,要求属性具有原子性,不可再分解;(只要是关系型数据库都满足1NF)

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

第三范式:3NF是对字段冗余性的约束,即我们的字段信息可以通过关联的关系,派生即可.(通常我们通过外键来处理)

但是,没有冗余的数据库未必是最好的数据库,有时为了提高运行效率,就必须降低范式标准,适当保留冗余数据。

具体做法是: 在概念数据模型设计时遵守第三范式,降低范式标准的工作放到物理数据模型设计时考虑。降低范式就是增加字段,允许冗余

适当的逆范式: 

想要既查询到图片的点击次数,也可以查询相册被点击的次数。单纯在photos表中设置一个hits属性确实是符合3范式的,但是在

查询相册被点击的次数时,需要查询所有albumid为1的相册,然后将点击的次数相加,每次这样的查询效率是相当低的。那么不如在

相册表中设置一个hits属性,虽然违反了第三范式冗余了,但是效率大大提高了。

 错误的逆范式:

sql语句的优化

面试题 :sql语句有几类

ddl (数据定义语言) [create alter drop]

dml(数据操作语言)[insert delete upate ]

select

dtl(数据事务语句) [commit rollback savepoint]

dcl(数据控制语句) [grant  revoke]

MySQL客户端连接成功后,通过使用show [session|global] status 命令可以提供服务器状态信息。

其中的session来表示当前的连接的统计结果,global来表示自数据库上次启动至今的统计结果。默认是session级别的。
下面的例子:
show status like ‘Com_%’;
其中Com_XXX表示XXX语句所执行的次数。
重点注意:Com_select,Com_insert,Com_update,Com_delete通过这几个参数,

可以容易地了解到当前数据库的应用是以插入更新为主还是以查询操作为主,以及各类的SQL大致的执行比例是多少。

还有几个常用的参数便于用户了解数据库的基本情况。
Connections:试图连接MySQL服务器的次数
Uptime:服务器工作的时间(单位秒)
Slow_queries:慢查询的次数 (默认是10)

这里我们优化的重点是在 慢查询. (在默认情况下是10 ) 

显示查看慢查询默认时间的情况:show variables like 'long_query_time';

为了测试,我们搞一个海量表(mysql存储过程)

目的,就是看看怎样处理,在海量表中,查询的速度很快!

首先我们先建一个海量测试表:

压力测试sql脚本,生成1800000条的海量数据:

 View Code

 现在将慢查询的时间改为0.2s,set long_query_time=0.2;

(这种设置只是本次连接有效,设置永久有效需要再配置文件my.ini)

执行查找:select * from emp where empno=123456;    花费0.281s

查询慢查询的次数:show status like 'Slow_queries';

可见慢查询的次数已经为1.

查找:show variables like '%quer%';

可以查看查找的相关设置信息,从中可以看见show_query_log慢查询日志记录已经开启,记录的信息如下。

现在我们优化:加索引(性价比高,不需要开辟新的内存)

索引是最物美价廉的东西了。不用加内存,不用改程序,不用调sql,只要执行个正确的’create index’,

查询速度就可能提高百倍千倍,这可真有诱惑力。

可是天下没有免费的午餐,查询速度的提高是以插入、更新、删除的速度为代价的(因为要维护索引信息文件),这些写操作,增加了大量的I/O。

 (四种索引

在emp表的 empno建立索引.

alter table emp add primary key(empno);

建索引之前:

 建索引之后:

可看见.MYI索引文件变得非常大。

再次查询:

耗时0s,可见速度提高飞速。

 索引的原理:

 为什么加了索引速度变快?

 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的引用指针。

更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。在没有索引的情况下,数据库会遍历全部数据后选择符合条件的;

而有了相应的索引之后,数据库会直接在索引中查找符合条件的选项。

索引的代价:

1.磁盘占用(生成索引文件)

2.对dml(update delete insert )语句的效率影响

 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。

介绍一款非常重要工具 explain, 这个分析工具可以对 sql语句进行分析,可以预测你的sql执行的效率.

他的基本用法是:

explain sql语句G  (G可以使得显示呈列,便于查看 )

//根据返回的信息,我们可知,该sql语句是否使用索引,从多少记录中取出(rows,正是因为建立索引只需要从一个记录中取出),可以看到排序的方式.

删除索引后:

在一列上建立索引后只会在查询这一列的时候提高速度,但是其他列查询的速度不变。

在什么列上添加索引比较合适?

①       在经常查询的列上加索引.

②       列的数据,内容就只有少数几个值,不太适合加索引.

③       内容频繁变化,不合适加索引

下列几种情况下有可能使用到索引:
1,对于创建的多列索引,只要查询条件使用了最左边的列,索引一般就会被使用。

只对左边的列建立的索引:

2,对于使用like的查询,查询如果是  ‘%aaa’ 不会使用到索引

       ‘aaa%’ 会使用到索引。

下列的表将不使用索引:
1,如果条件中有or,即使其中有条件带索引也不会使用。
2,对于多列索引,不是使用的第一部分,则不会使用索引。
3,like查询是以%开头
4,如果列类型是字符串,那一定要在条件中将数据使用引号引用起来。否则不使用索引。
5,如果mysql估计使用全表扫描要比使用索引快,则不使用索引。

如何检测你的索引是否有效

 show status like 'Handler_read%';

结论: Handler_read_key 越大越少

Handler_read_rnd_next 越小越好

MyISAM 和 Innodb区别

  1. MyISAM 不支持外键, Innodb支持
  2. MyISAM 不支持事务, Innodb支持.
  3. 对数据信息的存储处理方式不同.(如果存储引擎是MyISAM的,则创建一张表,对于三个文件.frm .myd .myi, 如果是Innodb则只有一张文件 *.frm,数据存放到ibdata1)
  •  MyISAM:默认的MySQL存储引擎。如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高。其优势是访问的速度快。
  •  InnoDB:提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比MyISAM,写的处理效率差一些并且会占用更多的磁盘空间。

对于 MyISAM 数据库,删除数据信息,只删掉内容,但是不释放空间。需要定时对表进行碎片整理清理。

optimize table 表名

以下是MYISAM和Innodb在优化上的策略:

 View Code

优化group by 语句
默认情况,MySQL对所有的group by col1,col2进行排序。

这与在查询中指定order by col1, col2类似。

如果查询中包括group by但用户想要避免排序结果的消耗,则可以使用order by null禁止排序

不再使用文件排序:

有些情况下,可以使用连接来替代子查询。

因为使用join,MySQL不需要在内存中创建临时表。

如果想要在含有or的查询语句中利用索引,则or之间的每个条件列都必须用到索引,如果没有索引,则应该考虑增加索引或者使用union all操作。

 View Code

选择合适的数据类型:

在精度要求高的应用中,建议使用定点数(decimal)来存储数值,以保证结果的准确性

1000000.32 万

create table sal(t1 float(10,2));

可见存的结果不准确。用decimal存之后:

create table sal2(t1 decimal(10,2));

表的划分

对表水平划分:

 如果一个表的记录数太多了,比如上千万条,而且需要经常检索,那么我们就有必要化整为零了。

如果我拆成100个表,那么每个表只有10万条记录。当然这 需要数据在逻辑上可以划分。

一个好的划分依据,有利于程序的简单实现,也可以充分利用水平分表的优势。比如系统界面上只提供按月查询的功能,那么把表按月 拆分成12个,每个查询只查询一个表就了。

如果非要按照地域来分,即使把表拆的再小,查询还是要联合所有表来查,还不如不拆了。所以一个好的拆分依据是 最重要的。(UNION)

对表进行垂直划分:

有些表记录数并不多,可能也就2、3万条,但是字段却很长,表占用空间很大,检索表时需要执行大量I/O,严重降低了性能。

这个时候需要把大的字段拆分到另一个表,并且该表与原表是一对一的关系。 (JOIN)

联合查询(union)和连接查询(join)恰好表达了这两种方式的用法。

数据库参数配置

最重要的参数就是内存,我们主要用的innodb引擎,所以下面两个参数调的很大  

innodb_additional_mem_pool_size = 64M   innodb_buffer_pool_size =1G

对于myisam,需要调整key_buffer_size 当然调整参数还是要看状态,用show status语句可以看到当前状态,以决定改调整哪些参数

读写分离技术

如果数据库压力很大,一台机器支撑不了,那么可以用mysql复制实现多台机器同步,将数据库的压力分散。

 基本的原理是让主数据库处理事务性查询,而从数据库处理SELECT查询。数据库复制被用来把事务性查询导致的变更同步到集群中 的从数据库。

原文章来源地址:http://www.cnblogs.com/xiangkejin/p/6899779.html

原文地址:https://www.cnblogs.com/cc66/p/7204275.html