mysql数据库优化总结

一、数据库优化

为查询缓存优化你的查询

大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同的查询就不用操作表而直接访问缓存结果了。 

查看查询缓存是否打开:

mysql> show variables like '%query_cache%'; 

如果不是ON,修改配置文件以开启查询缓存:

> vi /etc/my.cnf

[mysqld]中添加:

query_cache_size = 20M

query_cache_type = ON

最后的忠告是不要轻易打开查询缓存,特别是写密集型应用。如果你实在是忍不住,可以将query_cache_type设置为DEMAND,这时只有加入SQL_CACHE的查询才会走缓存,其他查询(SQL_NO_CACHE)则不会,这样可以非常自由地控制哪些查询需要被缓存。

 

 EXPLAIN 你的 SELECT 查询 

 

选择正确的存储引擎 

innoDB 的趋势会是一个非常复杂的存储引擎,对于一些小的应用,它会比 MyISAM 还慢。他是它支持“行锁” ,于是在写操作比较多的时候,会更优秀。并且,他还支持更多的高级应用,比如:事务。 

myisam适合一些需要大量查询的应用。但其对于大量写操作并不是很好。因为它使用到的是表级锁,所以在你更新的时候,整张表都会被锁起来,试想一下,当你在更新某一行数据的时候,导致其他的行都无法被访问,这会不会  很难受呢。

 

垂直分割 

“垂直分割”是一种把数据库中的表按列变成几张表的方法,这样可以降低表的复杂度和字段的数目,从而达到优化的目的。(以前,在银行做过项目,见过一张表有100多个字段,很恐怖)

 

1.3 选取最适用的字段属性

  1. 在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小,
  2. 应该尽量把字段设置为NOTNULL
  3. 尽量将字段设置为整数类型int

1.4 使用连接(JOIN)来代替子查询(Sub-Queries)

1.5 使用联合(UNION)来代替手动创建的临时表

1.6 事务

BEGIN; INSER TINTO salesinfo SET CustomerID=14;UPDAT Einventory SET Quantity=11 WHERE item='book';COMMIT;

第一个表中成功更新后,数据库突然出现意外状况,造成第二个表中的操作没有完成,这样,就会造成数据的不完整,甚至会破坏数据库中的数据。要避免这种情况,就应该使用事务,它的作用是:要么语句块中每条语句都操作成功,要么都失败。换句话说,就是可以保持数据库中数据的一致性和完整性。

1.7 索引

  1. 索引应建立在那些将用于join,where判断和order by排序的字段上。
  2. 尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个整数类型的字段来说,出现大量重复值是很有可能的况。
  3. 索引不会包含有NULL值的列  所以建议加索引的字段最好设置为NOTNULL
  4. like查询的时候,%在后面才会使用到索引
  5. 不要在列上进行运算    举例:select * from users where YEAR(adddate)<2007;将在每个行上进行运算,这将导致索引失效而进行全表扫描,  因此我们可以改成select * from users where adddate<‘2007-01-01';

1.8 请尽量指定需要查询的列,不要偷懒使用select *

1.9 限制返回的查询结果条数,若只需要一条查询结果,则用limit限定查询结果大小

1.10 尽量少在where条件后面加复杂的计算逻辑

 

二、数据库索引失效而全表扫描的情况

2.1 不要对where子句中对字段进行函数、表达式操作

2.2 where 子句中使用不等操作符(<>、!=)

2.3 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描

2.4 where 子句中使用or 来连接条件

原因:如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描

2.5 in 和 not in 也要慎用

注:在mysql数据库中where 子句中对索引字段使用 in 和 not in操作符,引擎不会放弃使用索引。

注:在mysql数据库中where 子句中对不是索引字段使用 in 和 not in操作符,会导致全表扫描。

2.6 like模糊查询,%在后面才会使用到索引,%在前面会导致全表扫描

 

三、数据库分库分表

3.1 分表

  数据量的日剧增加,数据库中某个表有几百万条数据,导致查询和插入耗时太长,怎么能解决单表压力呢?你就该考虑是否把这个表拆分成多个小表,来减轻单个表的压力,提高处理效率,此方式称为分表。

  分表技术比较麻烦,要修改程序代码里的SQL语句,还要手动去创建其他表,也可以用merge存储引擎实现分表,相对简单许多。分表后,程序是对一个总表进行操作,这个总表不存放数据,只有一些分表的关系,以及更新数据的方式,总表会根据不同的查询,将压力分到不同的小表上,因此提高并发能力和磁盘I/O性能。

mysql分表,分区 

什么是分表,从表面意思上看呢,就是把一张表分成N多个小表;如按时间分、按用户首字母分、按类别分等等

什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块可以在同一个磁盘上,也可以在不同的磁盘上;如mysql分成对应三个文件,一个.MYD数据文件,.MYI索引文件,.frm表结构文件。 
 

1、数据库如何实现分库分表?

两种方案:垂直和水平。

垂直拆分:根据业务进行拆分,比如可以分库订单数据库,商品数据库,支付数据库等。

水平拆分:即根据表来进行分割:比如user表可以拆分为user0,、user1、user2、user3等等

记录一次经历的数据库从单库到分库分表的过程:https://www.cnblogs.com/xiaohanlin/p/7499601.html

InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。 

MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比较低,也可以使用。

MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。

 

2、明确几个概念的含义

1、分区    

就是把一张表的数据分成N个区块,在逻辑上看最终只是一张表,但底层是由N个物理区块组成的

分区并不是生成新的数据表,而是将表的数据均衡分摊到不同的硬盘,系统或是不同服务器存储介子中,实际上还是一张表。另外,分区可以做到将表的数据均衡到不同的地方,提高数据检索的效率,降低数据库的频繁IO压力值,分区的优点如下:

1、相对于单个文件系统或是硬盘,分区可以存储更多的数据;

2、数据管理比较方便,比如要清理或废弃某年的数据,就可以直接删除该日期的分区数据即可;

3、精准定位分区查询数据,不需要全表扫描查询,大大提高数据检索效率;

4、可跨多个分区磁盘查询,来提高查询的吞吐量;

5、在涉及聚合函数查询时,可以很容易进行数据的合并;

1、水平分区

这种形式分区是对表的行进行分区,通过这样的方式不同分组里面的物理列分割的数据集得以组合,从而进行个体分割(单分区)或集体分割(1个或多个分区)。所有在表中定义的列在每个数据集中都能找到,所以表的特性依然得以保持。

2、垂直分区

这种分区方式一般来说是通过对表的垂直划分来减少目标表的宽度,使某些特定的列被划分到特定的分区,每个分区都包含了其中的列所对应的行。

举个简单例子:一个包含了大text和BLOB列的表,这些text和BLOB列又不经常被访问,这时候就要把这些不经常使用的text和BLOB了划分到另一个分区,在保证它们数据相关性的同时还能提高访问速度。

在数据库供应商开始在他们的数据库引擎中建立分区(主要是水平分区)时,DBA和建模者必须设计好表的物理分区结构,不要保存冗余的数据(不同表中同时都包含父表中的数据)或相互联结成一个逻辑父对象(通常是视图)。这种做法会使水平分区的大部分功能失效,有时候也会对垂直分区产生影响。

 

2、分片

对业务透明,在物理实现上分成多个分片,不同的分片在不同服务器上。

简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。 
数据的切分(Sharding)根据其切分规则的类型,可以分为两种切分模式。

(1)一种是按照不同的表(或者Schema)来切分到不同的数据库(主机)之上,这种切分可以称之为数据的垂直(纵向)切分
(2)另外一种则是根据表中的数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面,这种切分称之为数据的水平(横向)切分。

 

3、分表

把一张表按一定的规则分解成N个具有独立存储空间的实体表,系统读写时需要根据定义好的规则得到对应的字表名。

同库分表:所有的分表都在一个数据库中,由于数据库中表名不能重复,因此需要把数据表名起成不同的名字。

  • 优点:由于都在一个数据库中,公共表,不必进行复制,处理更简单。
  • 缺点:由于还在一个数据库中,CPU、内存、文件IO、网络IO等瓶颈还是无法解决,只能降低单表中的数据记录数。表名不一致,会导后续的处理复杂(参照mysql meage存储引擎来处理)

不同库分表:由于分表在不同的数据库中,这个时候就可以使用同样的表名。

  • 优点:CPU、内存、文件IO、网络IO等瓶颈可以得到有效解决,表名相同,处理起来相对简单。
  • 缺点:公共表由于在所有的分表都要使用,因此要进行复制、同步。一些聚合的操作,join,group by,order等难以顺利进行。

 

4、分库

  分表和分区都是基于同一个数据库里的数据分离技巧,对数据库性能有一定提升,但是随着业务数据量的增加,原来所有的数据都是在一个数据库上的,网络IO及文件IO都集中在一个数据库上的,因此CPU、内存、文件IO、网络IO都可能会成为系统瓶颈。

当业务系统的数据容量接近或超过单台服务器的容量、QPS/TPS接近或超过单个数据库实例的处理极限等。此时,往往是采用垂直和水平结合的数据拆分方法,把数据服务和数据存储分布到多台数据库服务器上。

分库只是一个通俗说法,更标准名称是数据分片,采用类似分布式数据库理论指导的方法实现,对应用程序达到数据服务的全透明和数据存储的全透明

 

分库分表区别   

1.数据处理上 (分表呢是利用了merge存储引擎(分表的一种))

a),分表后,数据都是存放在分表里,总表只是一个外壳,存取数据发生在一个一个的分表里面。看下面的例子: 

select * from alluser where id='12'表面上看,是对表alluser进行操作的,其实不是的。是对alluser里面的分表进行了操作。 

b),分区呢,不存在分表的概念,分区只不过把存放数据的文件分成了许多小块,分区后的表呢,还是一张表。数据处理还是由自己来完成。 

2.提高性能上 

a) 分表后,单表的并发能力提高了,磁盘I/O性能也提高了。并发能力为什么提高了呢,因为查寻一次所花的时间变短了,如果出现高并发的话,总表可以根据不同 的查询,将并发压力分到不同的小表里面。磁盘I/O性能怎么搞高了呢,本来一个非常大的.MYD文件现在也分摊到各个小表的.MYD中去了。 

这些区块可以在同一个磁盘上,也可以在不同的磁盘上
b)mysql提出了分区的概念,我觉得就想突破磁盘I/O瓶颈,想提高磁盘的读写能力,来增加mysql性能。 
在这一点上,分区和分表的测重点不同,分表重点是存取数据时,如何提高mysql并发能力上;而分区呢,如何突破磁盘的读写能力,从而达到提高mysql性能的目的。 

 

 

你可能感兴趣的:(Mysql)