优化:综合1

表分区与分表

什么是表分区?

表分区,是指根据一定规则,将数据库中的一张表分解成多个更小的,容易管理的部分。

从逻辑上看,只有一张表,但是底层却是由多个物理分区组成。

表分区与分表的区别

分表:指的是通过一定规则,将一张表分解成多张不同的表。比如将用户订单记录根据时间成多个表。

分表与分区的区别在于:分区从逻辑上来讲只有一张表,而分表则是将一张表分解成多张表。

表分区有什么好处?

1、存储更多数据。分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。

     和单个磁盘或者文件系统相比,可以存储更多数据

2、优化查询。在where语句中包含分区条件时,可以只扫描一个或多个分区表来提高查询效率;

     涉及sum和count语句时,也可以在多个分区上并行处理,最后汇总结果。

3、分区表更容易维护。例如:想批量删除大量数据可以清除整个分区。

4、避免某些特殊的瓶颈,例如InnoDB的单个索引的互斥访问,ext3问价你系统的inode锁竞争等。

分区表的限制因素

一个表最多只能有1024个分区

MySQL5.1中,分区表达式必须是整数,或者返回整数的表达式。

在MySQL5.5中提供了非整数表达式分区的支持。

如果分区字段中有主键或者唯一索引的列,那么多有主键列和唯一索引列都必须包含进来。

即:分区字段要么不包含主键或者索引列,要么包含全部主键和索引列。

分区表中无法使用外键约束

MySQL的分区适用于一个表的所有数据和索引,不能只对表数据分区而不对索引分区,

也不能只对索引分区而不对表分区,也不能只对表的一部分数据分区。

如何判断当前MySQL是否支持分区?

命令:

show variables like '%partition%'

运行结果:have_partintioning 的值为YES,表示支持分区。

MySQL支持的分区类型有哪些?

RANGE分区:

这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区

LIST分区:

这种模式允许系统通过预定义的列表的值来对数据进行分割。

按照List中的值分区,与RANGE的区别是,range分区的区间范围值是连续的。

HASH分区 :

这中模式允许通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。

例如可以建立一个对表主键进行分区的表。

KEY分区 :

上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。

大表优化

1. 限定数据的范围

务必禁止不带任何限制数据范围条件的查询语句。

比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内;

2. 读/写分离

经典的数据库拆分方案,主库负责写,从库负责读;

3. 垂直分区

根据数据库里面数据表的相关性进行拆分。

例如,用户表中既有用户的登录信息又有用户的基本信息,

可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。

简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。

如下图所示,这样来说大家应该就更容易理解了。

 

 

 垂直拆分的优点:

可以使得列数据变小,在查询时减少读取的Block数,减少I/O次数。

此外,垂直分区可以简化表的结构,易于维护。

垂直拆分的缺点:

主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。

此外,垂直分区会让事务变得更加复杂;

4. 水平分区

保持数据表结构不变,通过某种策略存储数据分片。

这样每一片数据分散到不同的表或者库中,达到了分布式的目的。

水平拆分可以支撑非常大的数据量。

水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,

这时可以把一张的表的数据拆成多张表来存放。

举个例子:

我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。

 

 

水平拆分可以支持非常大的数据量。

需要注意的一点是:

分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,

其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好分库 。

水平拆分能够 支持非常大的数据量存储,应用端改造也少,

但 分片事务难以解决 ,跨节点Join性能较差,逻辑复杂。

《Java工程师修炼之道》的作者推荐 尽量不要对数据进行分片,

因为拆分会带来逻辑、部署、运维的各种复杂度 ,

一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。

如果实在要分片,尽量选择客户端分片架构,这样可以减少一次和中间件的网络I/O。

客户端代理:

分片逻辑在应用端,封装在jar包中,通过修改或者封装JDBC层来实现。

当当网的 Sharding-JDBC 、阿里的TDDL是两种比较常用的实现。

中间件代理:

在应用和数据中间加了一个代理层。分片逻辑统一维护在中间件服务中。、

我们现在谈的 Mycat 、360的Atlas、网易的DDB等等都是这种架构的实现。

 

 

数据库表创建注意事项

字段名及字段配制合理性

  1. 剔除关系不密切的字段;
  2. 字段命名要有规则及相对应的含义(不要一部分英文,一部分拼音,还有类似a.b.c这样不明含义的字段);
  3. 字段命名尽量不要使用缩写(大多数缩写都不能明确字段含义);
  4. 字段不要大小写混用(想要具有可读性,多个英文单词可使用下划线形式连接);
  5. 字段名不要使用保留字或者关键字;
  6. 保持字段名和类型的一致性;
  7. 慎重选择数字类型;
  8. 给文本字段留足余量;


系统特殊字段处理及建成后建议

  1. 添加删除标记(例如操作人、删除时间);
  2. 建立版本机制;


表结构合理性配置

  1. 多型字段的处理,就是表中是否存在字段能够分解成更小独立的几部分(例如:人可以分为男人和女人);
  2. 多值字段的处理,可以将表分为三张表,这样使得检索和排序更加有调理,且保证数据的完整性

其它建议

  1. 对于大数据字段,独立表进行存储,以便影响性能(例如:简介字段);
  2. 使用varchar类型代替char,因为varchar会动态分配长度,char指定长度是固定的;
  3. 给表创建主键,对于没有主键的表,在查询和索引定义上有一定的影响;
  4. 避免表字段运行为null,建议设置默认值(例如:int类型设置默认值为0)在索引查询上,效率立显;
  5. 建立索引,最好建立在唯一和非空的字段上,建立太多的索引对后期插入、更新都存在一定的影响(考虑实际情况来创建);

 

查询缓存的使用

执行查询语句的时候,会先查询缓存。不过,MySQL 8.0 版本后移除,因为这个功能不太实用

my.cnf加入以下配置,重启MySQL开启查询缓存

query_cache_type=1

query_cache_size=600000

MySQL执行以下命令也可以开启查询缓存

set global  query_cache_type=1;

set global  query_cache_size=600000;

如上,开启查询缓存后在同样的查询条件以及数据情况下,会直接在缓存中返回结果。

这里的查询条件包括查询本身、当前要查询的数据库、客户端协议版本号等一些可能影响结果的信息。

因此任何两个查询在任何字符上的不同都会导致缓存不命中。

此外,如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL库中的系统表,其查询结果也不会被缓存。

缓存建立之后,MySQL的查询缓存系统会跟踪查询中涉及的每张表,

如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效。

缓存虽然能够提升数据库的查询性能,

但是缓存同时也带来了额外的开销,每次查询后都要做一次缓存操作,失效后还要销毁。

因此,开启缓存查询要谨慎,尤其对于写密集的应用来说更是如此。

如果开启,要注意合理控制缓存空间大小,一般来说其大小设置为几十MB比较合适。

此外,还可以通过sql_cache和sql_no_cache来控制某个查询语句是否需要缓存:

select sql_no_cache count(*) from usr; 

MySQL优化总结

1、开启查询缓存,优化查询

2、explain你的select查询,这可以帮你分析你的查询语句或是表结构的性能瓶颈。EXPLAIN 的查询结果还会告诉你你的索引主键被如何利用的,你的数据表是如何被搜索和排序的

3、当只要一行数据时使用limit 1,MySQL数据库引擎会在找到一条数据后停止搜索,而不是继续往后查少下一条符合记录的数据

4、为搜索字段建索引

5、使用 ENUM 而不是 VARCHAR,如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是VARCHAR。

6、Prepared StatementsPrepared Statements很像存储过程,是一种运行在后台的SQL语句集合,我们可以从使用 prepared statements 获得很多好处,无论是性能问题还是安全问题。Prepared Statements 可以检查一些你绑定好的变量,这样可以保护你的程序不会受到“SQL注入式”攻击

7、垂直分表

8、选择正确的存储引擎

posted @ 2019-12-12 22:07  弱水三千12138  阅读(132)  评论(0编辑  收藏  举报