MySQL优化数据库对象

1、优化表的数据类型

使用PROCEDURE ANALYSE()对当前应用的表进行分析,该函数可以对数据表中列的数据类型提供优化建议。

select* from tbl_name PROCEDURE ANALYSE();
select* from tbl_name PROCEDURE ANALYSE(16,256);

第二句告诉PROCEDURE ANALYSE()不要为那些包含的值多于16个或者256个字节的ENUM类型提出建议。


整型数据优化

存储人的年龄应该使用哪种数据类型?答:使用tinyint类型(无符号型)

存储乌龟的年龄应该使用哪种数据类型?答:使用smallinit类型(无符号型)

存储一个1500万数据的数据表其主键id应该选择哪种数据类型?答:使用mediumint(无符号型),大约在0-1600万左右

①考虑空间问题

②考虑范围问题(unsigned无符号)

字符串类型优化

char(length)占用的空间为 固定的,与内容多少无关;

varchar(length)占用的空间为 实际内容字符个数*字节 + 1

如果要存储一个11位的手机号码?答:选择char11)比较合适

如果要存储一个32位的md5加密密码?答:选择char32)比较合适

如果要存储一个用户名或一个标题,由于不确定具体要存放多少个字符,为了避免空间的浪费建议使用varchar类型。

如果要存储一个描述信息(不超过250个汉字),使用varchar255)比较合适。

如果要存储一个文本信息(文章内容),其超过了255个字符,建议使用text文本类型。

时间类型优化

在实际应用中,由于date类型主要用于存储时间信息,但是在php中,我们有相关的函数可以对整型数据和时间进行转化,所以实际应用中,大部分情况存储时间都是转化为整型数据直接存储的

5、枚举类型与集合类型

如果程序中有单选或多选情况,不建议使用varchar类型,而建议使用枚举类型或集合类型。

、IP类型数据的存储

经常要保存IP地址,这个时候不建议使用varchar类型来保存数据,而建议使用整型来保存IP信息

//php中ip转整形

echo ip2long("192.168.1.1");

//整形转ip

echo long2ip(3232235777);

2、通过拆分提高表的访问效率

这里所说的”拆分”,是指对数据表进行拆分。若针对MyISAM类型的表进行,大体有两种拆分方法。

1 第一种方法是垂直拆分,即把主码和一些列放到一个表,然后把主码和另外的列放到另一个表中。

如果一个表中某些列常用,而另一些列不常用,则可以采用垂直拆分,另外,垂直拆分可以使得数据行变小,一个数据页就能存放更多的数据,在査询时就会减少I/O次数。其缺点是 需要管理冗余列,査询所有数据需要联合(join)操作。

2 第二种方法是水平拆分,即根据一列或多列数据的值把数据行放到两个独立的表中。 水平拆分通常在以下几种情况下使用。

表很大,分割后可以降低在查询时需要读的数据和索引的页数,同时也降低了索引的层数,提高查询速度.表中的数据本来就有独立性.

例如,表中分别记录各个地区的数据或不同时期的数据, 特别是有些数据常用,而另外一些数据不常用需要把数据存放到多个介质上.

例如,移动电话的账单表就可以分成两个表或多个表。最近3个月的账单数据存在一个表 中,3个月前的历史账单存放在另外一个表中,超过1年的历史账单可以存储到单独的存储介质上,这种拆分是最常使用的水平拆分方法.

总结: 
水平拆分会给应用增加复杂度,它通常在査询时需要多个表名,査询所有数据需要UNION 操作。在许多数据库应用中,这种复杂性会超过它带来的优点,因为只要索引关键字不大,则 在索引用于査询时,表中增加2〜3倍数据量,査询时也就增加读一个索引层的磁盘次数,所以水平拆分要考虑数量额增长速度,根据实际情况决定是否需要对表进行水平拆分.

3、逆规范化

数据库设计时要满足规范化这个道理大家都非常清楚,甚至有数据库的三范式, 好吧, 这有点让我想起了机器人的三定律.但是否数据的规范化程度越高越好呢?这还是由实际需求来决定。

  • 因为规范化越高,那么产生的关系就越多,关系过多的直接结果就是导致表之间的连接操作越频繁,而表之间的连接操作是性能较低的操作,直接影响到査询的速度,所以,对于査询较多的应用,就需要根据实际情况运用逆规范化对数据进行设计,通过逆规范化来提高査询的性能。

    例如,移动电话的用户每月都会査询自己的账单,账单信息一般包含用户的名字和本月消费总金额,设想一下,如果用户的姓名和属性信息存放在一个表中,假设表名为A,而用户的 编号和他对应的账单信息存放在另外一张B表中,那么,用户每次查询自己的月账单时,数据库査询时都要进行表连接,因为账单表B中并不包含用户的名字,所以必须通过关联A表取 过来,如果在数据库设计时考虑到这一点,就可以在B表增加一个冗余字段存放用户的名字, 这样在査询账单时就不用再做表关联,可以使査询有更好的性能。

反规范的好处是降低连接操作的需求、降低外码和索引的数目,还可能减少表的数目,相 应带来的问题是可能出现数据的完整性问题。加快查询速度,但会降低修改速度。因此,决定 做反规范时,一定要权衡利弊,仔细分析应用的数据存取需求和实际的性能特点,好的索引和 其他方法经常能够解决性能问题,而不必采用反规范这种方法。

在进行反规范操作之前,要充分考虑数据的存取需求、常用表的大小、一些特殊的计算(例 如合计)、数据的物理存储位置等。常用的反规范技术有增加冗余列、增加派生列、重新组表 和分割表。

  • 增加冗余列:指在多个表中具有相同的列,它常用来在查询时避免连接操作。
  • 增加派生列:指增加的列来自其他表中的数据,由其他表中的数据经过计算生成。增 加的派生列其作用是在查询时减少连接操作,避免使用集函数。
  • 重新组表:指如果许多用户需要查看两个表连接出来的结果数据,则把这两个表重新 组成一个表来减少连接而提高性能.

另外,逆规范技术需要维护数据的完整性。无论使用何种反规范技术,都需要一定的管理 来维护数据的完整性,常用的方法是批处理维护、应用逻辑和触发器。 
1. 批处理维护是指对复制列或派生列的修改积累一定的时间后,运行一批处理作业或存 储过程对复制或派生列进行修改,这只能在对实时性要求不高的情况下使用. 
2. 数据的完整性也可由应用逻辑来实现,这就要求必须在同一事务中对所有涉及的表进 行增、删、改操作.用应用逻辑来实现数据的完整性风险较大,因为同一逻辑必须在所有的应 用中使用和维护,容易遗漏,特别是在需求变化时,不易于维护。 
3. 另一种方式就是使用触发器,对数据的任何修改立即触发对复制列或派生列的相应修 改,触发器是实时的,而且相应的处理逻辑只在一个地方出现,易于维护•一般来说,是解决 这类问题比较好的办法。

4、使用中间表提高统计查询速度

对于数据量较大的表,在其上进行统计查询通常会效率很低,并且还要考虑统计查询是否会对在线的应用产生负面影响。通常在这种情况下,使用中间表可以提高统计查询的效率,下面通过对session 表的统计来介绍中间表的使用:
(1)session 表记录了客户每天的消费记录,表结构如下:
CREATE TABLE session (
cust_id varchar(10) , --客户编号
cust_amount DECIMAL(16,2), --客户消费金额
cust_date DATE, --客户消费时间
cust_ip varchar(20) –客户IP 地址
)
(2)由于每天都会产生大量的客户消费记录,所以session 表的数据量很大,现在业务部门有一具体的需求:希望了解最近一周客户的消费总金额和近一周每天不同时段用户的消费总金额。针对这一需求我们通过2 种方法来得出业务部门想要的结果。
方法1:在session 表上直接进行统计,得出想要的结果。
mysql> select sum(cust_amount) from session where cust_date>adddate(now(),-7);
+------------------+
| sum(cust_amount) |
+------------------+
| 161699200.64 |
+------------------+
1 row in set (3.95 sec)


方法2:创建中间表tmp_session,表结构和源表结构完全相同。
CREATE TABLE tmp_session (
cust_id varchar(10) , --客户编号
cust_amount DECIMAL(16,2), --客户消费金额
cust_date DATE, --客户消费时间
cust_ip varchar(20) –客户IP 地址
) ;

转移要统计的数据到中间表,然后在中间表上进行统计,得出想要的结果。
mysql> insert into tmp_session select * from session where cust_date>adddate(now(),-7);
Query OK, 1573328 rows affected (6.67 sec)
Records: 1573328 Duplicates: 0 Warnings: 0
mysql> select sum(cust_amount) from tmp_session;
+------------------+
| sum(cust_amount) |
+------------------+
| 161699200.64 |
+------------------+


1 row in set (0.73 sec)


从上面的2 种实现方法上看,在中间表中做统计花费的时间很少(这里不计算转移数据花费的时间),另外,针对业务部门想了解“近一周每天不同时段用户的消费总金额”这一需求,在中间表上给出统计结果更为合适,原因是源数据表(session 表)cust_date 字段没有索引并且源表的数据量较大,所以在按时间进行分时段统计时效率很低,这时可以在中间表上对cust_date 字段创建单独的索引来提高统计查询的速度。中间表在统计查询中经常会用到,其优点如下:
 中间表复制源表部分数据,并且与源表相“隔离”,在中间表上做统计查询不
会对在线应用产生负面影响。
 中间表上可以灵活的添加索引或增加临时用的新字段,从而达到提高统计查询
效率和辅助统计查询作用。


猜你喜欢

转载自blog.csdn.net/qq_22238021/article/details/80931413
今日推荐