Mysql 优化 -- 数据库结构

Posted luojiahu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql 优化 -- 数据库结构相关的知识,希望对你有一定的参考价值。

以下内容仅针对mysql InnoDB引擎。内容主要来自Mysql 5.6版本Reference Manual。

1 优化数据结构设计

针对表结构进行仔细的设计是十分必要的,因为紧凑的数据结构设计能够显著地减少在磁盘交互时所需要交换的数据量、内存中所需的空间大小。以及,能够相应地减少索引所占的空间。总之,对数据结构进行优化设计能够从速度及空间两方面得到提升,从而提升性能。

1.1 列设计

  • 在满足需求的情况下,只使用能够满足需求(尽量小)的数据类型。例如,MEDIUMTEXT类型占用3个字节(-8388608-8388607),而INT类型占用4个字节的存储空间(-2147483648-2147483647),相对能够节省25%的存储空间。
  • 如果可能,将列声明为NOT NULL。主要从两个方面获益:对于建在非空列上的索引,mysql在使用索引时能够避免检测该列是否为空的额外消耗,从而提高性能;对于每行数据,能够节省1 bit的用来表示此行是否为空的存储空间。

1.2 Row Format设计

在5.6版本中,InnoDB引擎默认的行存储格式为COMPACT。COMPACT,DYNAMIC和COMPRESSED都是同一系列的紧凑型行存储格式,这类存储格式能够降低数据在磁盘的存储空间,带来的负面影响是在某些操作中导致高CPU消耗。如果Mysql性能提升受限于磁盘速度或者缓存命中率,这类型格式能够提升性能表现。而如果Mysql已经达到了CPU瓶颈,采用这种格式可能导致更查的性能表现。

1.3 索引设计

  • 主键(primary key)所占长度应尽可能短。速度上,越短的主键使得能够迅速确定表中的对应行。空间上,对于InnoDB,每个二级索引(secondary index)都会保存一份主键的复制,所以更短的主键能够显著地减少存储空间。
  • 只创建必须的索引来提升查询性能。因为索引虽然能够提升查询性能,但是会造成插入和更新变慢。
  • 如果通过多列限制条件对表进行查询,针对多个条件列创建组合索引,而不要在每一列上单独创建索引。
  • 如果针对表的查询以多列条件查询为通常情况,组合索引中的第一列应为具有最多重复值的列,以此获得更好的索引压缩。(//TODO)

1.4 联结查询(Join)

  • 在某些情况下,将查询频率较高的表转换为两张表进行联合查询能够提升性能。
  • 对于联合查询的表,将联结条件列类型及大小声明为完全一致
  • 保持列名简单,以便能够在多表联合查询的时候使用同样的列名。例如,对于客户表(customer)姓名列声明为name而不是customer_name。

1.5 范式

通常地,应当遵循范式规定,保持数据的低冗余,对于占用较长长度的列单独存储并用id进行关联获取。但在需要获取较好的查询性能的情况下,可以通过数据冗余来提升性能表现。

2 优化数据类型

2.1 数字型

对于唯一ID或者使用数字或字符表示均可的情况,尽可能使用数字类型。因为数字类型通常占用更少的存储空间,并且在类型转换和大小比较时速度更快。

2.2 字符型

  • 使用二进制(binary)collation,以在排序和比较操作时获得更快的速度。
  • 当需要对不同列的数据进行比较时,将这些列声明为相同的编码类型和collation类型。以避免二外的类型转换。
  • 对于小于8KB的字符数据,使用VARCHAR类型,不要采用BLOB类的字段类型。ORDER BY和GROUP BY时产生的临时表,当原始表中没有BLOB类的字段类型时,能够采用MEMORY引擎。(对于utf8编码格式,VARCHAR类型大概能够存储2.7K汉字)
  • 当表中有较长的字符型数据字段,例如地址、姓名,而落在该表上的查询通常并不需要返回这些字段时,可以考虑独立建立一张表存储这些字段。这主要是因为,Mysql在读取某一行的某列数据时,会将该行所在的所有列(还可能包括相邻列)都读取。采用这种分表存储的方式,能够显著减少数据读取时的硬盘I/O和内存占用。
  • 在InnoDB引擎下,对于使用随机产生的值作为主键列的情况,尽可能使用有序的值(例如时间或者日期)作为前缀,以使数据保存尽可能紧凑,这样mysql在读取或者写入时能够更快。

2.3 BLOB类型

  • 对于使用BLOB存储的文本,首先应当考虑对其进行压缩。
  • 与字符型类似,当查询通常不需返回BLOB字段时,考虑分表存储
  • 考虑使用独立的存储设备(SSD)或者数据库实例对其进行存储。
  • 不要对非常长的列进行是否相等的比较,可以通过对内容进行HASH的结果单独存储并在其上建立索引来获得更好的性能表现,在比较时通过HASH列获取更好的性能,然后使用原数据列进行比较得到最终的比较结果。

2.4 使用PROCEDURE ANALYSE进行分析

ANALYSE通过对指定的查询进行分析,返回建议的数据类型优化结果。通过如下句式使用:

SELECT … FROM … WHERE … PROCEDURE ANALYSE(max_elements, [max_memory])

max_elements(默认为256),指定每行分析时每行独立值的个数。

max_memory(默认为8192),指定分析时每列分配的内存大小。

3 内部临时表

在某些情况下,mysql会产生临时表,而用户对这些表并不能取得任何操作控制权限。

产生临时表的常见场景有:子查询、GROUP BY … ORDRER BY 组合 或者 DISTINCT … ORDER BY 组合导致的临时表等。当Msysql创建了临时表时,Created_tmp_table状态变量会对应增加,当临时表为磁盘临时表时,Create_tmp_disk_table会对应增加。

产生磁盘临时表的情况主要有:

  • BLOB或者TEXT列
  • 超过512 byte(二进制字符型)或者512个字符(非二进制)的列出现在GROUP BY 或者 DISTINCT后
  • 使用UNION或者UNION ALL,同时查询列中含有超过512 byte(二进制字符型)或者512个字符(非二进制)的列

对于内存中的临时表,其存储引擎为MEMORY;对于磁盘临时表,其存储引擎为MyISAM。

【Reference】

MySQL 5.6 Reference Manual

以上是关于Mysql 优化 -- 数据库结构的主要内容,如果未能解决你的问题,请参考以下文章

Mysql 优化 -- 数据库结构

Mysql 性能优化5重要数据库结构优化

Mysql性能优化----SQL语句优化索引优化数据库结构优化系统配置优化服务器硬件优化

MySQL性能优化方法二:表结构优化

mySQL表结构优化

mysql索引优化分析