对一个设计拙劣或者没有做index的schma进行优化,可以很大程度的改善性能。
如果想获得很好的性能,就需要对你运行的特定的queries来设计schema和索引,
你需要估计不同类query的性能需求,和使用的频度,以及需要检索的字段和检索
的条件。优化是一个权衡,索引可以提高检索速度,但是会降低更新速度,一个反
范式的schema可能会在某些查询下加快速度,但在其他情况下可能降低速度。添加
冗余字段、计数器、summary表可以优化查询,但是维护起来很困难。
选择最优的数据类型:
Mysql支持大量的各种个样的数据类型,如何正确的选择类型来存储数据是产生高性能
的关键。
1.足够大的越小的类型越好
小的类型通常更高效,因为他们使用了更少的磁盘空间、内存和cpu高速缓存,需要更少
的CPU时钟周期。但是也不要低估的存储值的范围,增大schema多个地方的数据类型也是
一件痛苦和耗时的操作。
2.简单就好:
简单的类型需要更少的时钟周期,整数的比较要比字符串的比较要快。,比如你应该存储
mysql内置的类型而不是字符串来存贮日期和时间,使用整数来存储ip。
3.尽可能避免null字段:
尽可能的在定义的字段上添加NOT NULL,MySQL对于可以为null的列很难优化,
因为它让索引、索引统计以及值的比较变得复杂,nullable的列会使用更多的存储空间,并且需要一些特殊处理,对nullable的列建索引,每个entry需要额外的数据,在MyISAM甚至会使定长索引变成变长的。对于没有值的列,你可以使用一些特殊的值来代表,比如0,空字符串。将null变成not null可能对性能的提高不是很大,但是如果你打算对一个列见索引,那么要避免它是nullable的。
选择一个列的数据类型,首先决定大体上是什么类型的:整数、字符串等等。然后在再这些类型中选择合适的MySQL提供的类型。比如DATETIME和TIMESTAMPE可以存储相同的数据:日期和时间,精度为1秒。但是Timestamp使用了一半的空间,并且是时区敏感和一些特殊的自动更新的功能。但是具有很小的值的范围,到2038年就over了。
MYSQL为了兼容性提供了很多的别名,比如INTEGER,BOOL,NUMERIC,他们只是别名,不影响性能。
数字类型:
数字类型包括整数和浮点数类型,整数类型tinyint,smallint,mediumint,int,
bigint,他们分别占8,16,24,32,64个字节。整数类型可以使用unsigned属性,
tinyint unsigned可以存储0~255。MySQL的整数计算通常使用的是64位的bigint。
MySQL可以指定整数类型的宽度,但是这个宽度并不是限制数据的范围,只是用于指定交互式的工具显示保留的字符个数,在存储上INT(1)和INT(20)是等价的。
浮点类型:
浮点书类型有小数部分,但是他们并不是仅仅针对浮点数的,你可以使用DECIMAL来表示BIGINT存储不下的整数,MySQL支持两类:精确和非精确类型。
FLOAT和DOUBLE支持近似的标准的浮点计算,如果你需要知道计算的精确结果,你需要平台下浮点数的实现。DECIMAL可以存储精确的分数,MySQL5.0以上支持精确的数学计算,但是浮点类型的数学计算效率会更高,存储空间更小。浮点类型和DECIMAL都可以指定精度,比如DECIMAL(18,9).由于空间和计算的效率问题,只有需要精确的结果时,我们才使用DECIMAL。
字符串类型:
MySQL支持很多的字符串类型,从版本4.1开始,支持每个列使用一种字符集,如果这么做,会很大的影响性能。
VARCHAR和CHAR类型:
有两种主要的字符串类型VARCHAR和CHAR:
VARCHAR主要存储变长的字符类型,会比固定长度的类型要节省空间,因为它只需要和实际需要用的空间一样大,VARCHAR指定的长度并不是申请那么大的空间,只是最大可能占用的空间。使用1,2个额外的字节来存储长度,比如VARCHAR(10)最大会占11个字节,VARCHAR(1000)最大会占用1002个字节。
由于VARCHAR能够节省空间,所以有助于提高性能,但是由于行是变长的,如果行大到无法在原来的位置存储,那么在MyISAM会产生行碎片,InnoDB会分页。
MySQL 5.0以上不会自动删除掉结尾的空白。
通常在最长的数据要比平均的长度大很多,不会频繁更新这个字段的情况下使用VARCHAR。
CHAR是固定长度的类型,它会申请指定长度的空间。存储的时候默认会删除结尾的空白,
如果存储短的,并且长度差不多的字符串,使用CHAR是非常好的,比如存储MD5的用户密码。
对于频繁跟新的字段,使用CHAR也是比较好的选择,可以使用CHAR(1)来代表Y和N的值,这比VARCHAR(1)少用一个字节。
BINARY和VARBINARY类型用于存储二进制的字符串,和传统的字符串类似,只是存储的是字节而不是字母。BINARY字符串的比较要比普通字符串要快。
BLOB和TEXT类型:
BLOB和TEXT是用来存储大规模的数据的,分别用于二进制和字符串类型。还有其他同族的类型:TINYTEXT,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT,和二进制类型TINYBLOB,SMALLBLOB,BLOB,MEDIUMBLOB,LONGBLOB.
BLOB和TEXT的区别是一个用来存储二进制的,一个用来存储文本的他有字符集和编码。
BLOB和TEXT类型和其他类型排序不同,他不会将全部长度的字符串排序,他只会排序前
max_sort_length字节。如果你需要排序跟少的字符你可以减少max_sort_length,或者使用order by substring(column,length)。MySQL不能对这些类型的全部长度建索引,所以不能够使用索引来排序。
内存存储引擎不支持BLOB和TEXT类型,所以使用BLOB和TEXT列的查询,隐含的使用了On-disk临时表。即使你配置MySQL临时表在内存中,仍然需要很昂贵的系统调用。最佳的实践是不要使用BLOB和TEXT类型除非你真的需要,如果不可避免,那么可以使substring(column,length)类转换成字符串类型,这样可以使用in-memory表。需要确认使用足有短的substring,临时表的大小没有超出max_head_table_size或者tmp_table_size,否则会使用on-disk MyISAM表。
EXPLAIN的Extra列包含“Using temporary"表明这个查询使用了隐式的临时表。
使用ENUM来代替字符串类型
有时候我们可以使用ENUM列来代替传统的字符串类型,ENUM列可以存储65535个不同的字符串值。MySQL存储他们非常的紧凑,压缩为1~2个字节。每个值的内部存储都是一个整数,在.frm文件保存了数字到字符串的一个映射。
引用
mysql> CREATE TABLE enum_test(
->
e ENUM('fish', 'apple', 'dog') NOT NULL
-> );
mysql> INSERT INTO enum_test(e) VALUES('fish'), ('dog'), ('apple');
mysql> SELECT e + 0 FROM enum_test;
+-------+
| e + 0 |
+-------+
|
1 |
|
3 |
|
2 |
+-------+
ENUM字段排序是按照内部存储的整数排的,你可以显示的使用FIELD来指定排序的方式。
引用
mysql> SELECT e FROM enum_test ORDER BY FIELD(e, 'apple', 'dog', 'fish');
+-------+
| e
|
+-------+
| apple |
| dog
|
| fish |
+-------+
ENUM最大的缺点是字符串列表是固定大小的,添加和删除一个字符串需要使用ALTER TABLE,所以如果你表示的字符串有可能在将来改变,那么使用ENUM并不是一个好的主意。
如果ENUM需要和char,varchar进行join操作,那么会慢一些,这时候最好同一类型,
但是使用ENUM能够比使用char,varchar节省不少空间的。
日期和时间类型:
MySQL有各种日期和时间的类型,比如YEAR,DATE,MySQL能存储的最小时间粒度是秒,但是可以在微妙级别做临时的运算。
DATETIME:
这个类型能够保存更大范围的值,从1001到9999,精度为1秒,他将日期和时间存储为整数格式为YYYYMMDDHHMMSS,和时区无关,使用了8个字节。
TIMESTAMP:
TIMESTAMP按照字面意思,存储了从1970.1.1流失了多少秒,和Unix的timestamp一样。
TIMESTAMP仅使用了4个自己,所以要比DATETIME小很多:从1970到2038. MySQL提供了
FROM_UNIXTIME()和UNIX_TIMESTAMP()函数来将Unix时间戳和日期转换。
TIMESTAMP是和时区相关的。
时间戳有一些DATETIME没有的功能,他没在插入数据的时候,如果该列为空,则自动将当前时间插入。当更新一行数据时,这行数据的TIMESTAMP列默认会跟新为当前时间,除非显式的指定值,TIMESTAMP列默认是NOT NULL的。
一般来说你应该使用TIMESTAMP,因为他比DATETIME占用更少的空间。有一些人喜欢存储
Unix时间戳为一个整数,但常常没有给你带来任何好处,因为这种格式不方便处理,我们并不推荐这么用。
Bit压缩类型(Bit-packed Data Types)
MySQL提供了一些存储类型,他每一个bit存储一个值来的更紧凑的存储数据方式。所有的
这些类型都是字符串类型,不管底层的存储格式和操作:
BIT 在MySQL5.0之前,BIT是TINYINT的同义词。但是在5.0之后,它是一个完全不同的类型,具有特殊的特性:你可以使用BIT列来存储true/false值。BIT(1)定义了包含了单个比特,BIT(2)存储了两个bit,BIT字段的最大值是64bit。
BIT类型的行为在不同的存储引擎中不同,MyISAM将这些列一起压缩存储,所以17个BIT列只需要17bit的存储空间(没有列是NULL的)。其他的存储引擎比如Memory和InnoDB,使用足够大的integer类型来存储,所以使用BIT并没有节省多少空间。
MySQL将BIT类型视为字符串类型而不是数字类型。如果使用BIT(1),查询出来的是一个字符串,内容是二进制的0或者1,但不是ASCCII码的‘0’,’1‘的值。
但是在数字的场景下使用,其值是字符串二进制表示的值,比如b'00111001'为57.
这可能会比较让人费解,所以我们建议谨慎的使用BIT,在大多数的应用中,避免使用。
如果想存储true/false中使用单个bit的存储空间,那么另外的选择是使用varchar(0),
这个列可以存储NULL或者空字符串。
SET
如果你想存储很多的true/false值,那么考虑将很多列组合成1列,使用SET数据类型,内部表示为压缩的bit集合。MySQL有函数FIND_IN_SET()和FIELD(),让在查询中使用
更容易。主要的缺点是,修改需要ALTER TABLE.
在整数列使用bit操作
另一种对于SET的选择是使用整数作为压缩的比特集合,比如你可以在TINYINT类型使用
8个bit,然后通过bit操作。这种方式相对于SET的最大有点是修改这个字段不需要ALTER TABLE。缺点是比较拿写和理解,位操作,有人喜欢有人不喜欢,所以完全看你的口味了。
选择主键:
选择一个主键的正确类型是非常重要的。你经常使用这些列来和其他的值比较,或者使用它来查找,在其他的表中作为外键。选择主键不仅仅药考虑存储的类型,还要考虑比较和计算的性能。比如MySQL存储ENUM和SET类型的内部形式是整数,但是在字符串的环境下会转化为字符串。
一旦选择好一个类型,要确保所有关联的表对应的外键具有相同的类型。类型要精确的匹配比较好,除了UNSIGNED。混用不同的类型可能导致性能问题,并且隐式的类型转换可能会带来错误。
选择能够包含数据区间的最小的类型,比如你想用state_id字段来存储美国的州,那么TINYINT已经足够。
整数类型:
通常是最佳的主键类型的选择,因为它速度快并且可以自增。
ENUM和SET:
通常是一个比较糟糕的选择,他们比较适合作为状态,类型的值。
String类型:
尽可能避免使用字符串类型的主键,因为占用较多的空间并且比整数慢。使用MyISAM的表更应该特别谨慎使用字符串类型的主键,因为他会默认压缩字符串索引,这会导致查询非常慢。
使用packed索引大约要慢六倍。
使用完全随机的字符串,比如MD5(),SHA1(),UUID(),要特别小心,每一个新生成的值都会
在一个很大空间的一个随机的值,这将会降低插入和部分查询语句。
INSERT慢的原因是插入的值在索引的随机位置,这会导致页的分裂或者磁盘的随机访问,对于聚集存储引擎会引起聚集索引碎片。
SELECT慢的原因逻辑相邻的行将会在磁盘和内存分散。
随机的值也会导致所有类型查询的缓存表现很差。
特殊类型数据:
比如很多人使用VARCHAR(15)来表示IP,其实IP是一个无符号的32为整数,所以存储IP地址为整数是一个比较好的方法。MySQL提供了INET_ATON()和INET_NTOA函数来转换这两种表示。
参考《高性能MySQL》
分享到:
相关推荐
MySQL 数据库查询优化方案 MySQL 数据库查询优化是指对数据库中的查询语句进行优化,以提高查询效率和数据库性能。以下是 MySQL 数据库查询优化的一些重要知识点: 一、索引相关 索引是 MySQL 数据库查询优化的...
MySQL GUI Tools是一款强大的图形用户界面工具集合,专为MySQL数据库管理系统设计,旨在简化数据库的管理和优化。这款工具集包括了多种实用工具,如MySQL Workbench、MySQL Query Browser、MySQL Administrator等,...
schema 设计是 MySQL 数据库中的一个重要概念,用于设计和定义数据库的结构。schema 设计包括数据库设计、表设计、索引设计等。 SQL 优化 SQL 优化是 MySQL 数据库中的一个重要概念,用于优化 SQL 语句的执行效率...
在【data-dictionary-master】目录下,你可能找到的是一个包含MySQL数据库字典相关代码或者文档的项目,这可能是一个开源项目,用于解析或展示MySQL的元数据信息。通过学习这个项目,你可以了解如何与MySQL的`...
MySQL数据库是世界上最受欢迎的开源关系型数据库之一,其高效使用对于任何依赖它的应用程序至关重要。这份“MySQL数据库高效使用规范”文档旨在提供关于如何优化MySQL性能、遵循最佳实践以及编写高效SQL代码的指导。...
接下来,"数据库SQL优化总结之百万级数据库优化.pdf"可能深入到实际的优化实践。 1. **数据库架构设计**:在百万级数据量下,合理的设计能避免性能瓶颈,如垂直分割、水平分割,以及读写分离策略。 2. **缓存与...
《数据库优化与集成之实战和效果》是由郑保卫编著的一本关于数据库管理与优化的专业教材,主要针对数据库系统在实际应用中的性能提升和不同数据库的整合策略进行深入探讨。PDF课件形式使得读者可以方便地在线学习或...
MySQL数据库中的`information_schema`和`mysql`数据库是系统核心组成部分,它们对于数据库的正常运行至关重要,因此绝对不应该被删除。 `information_schema`数据库是一个特殊的虚拟数据库,它并不存储实际的数据,...
MySQL是世界上最受欢迎的关系型数据库管理系统之一,用于存储和管理各种数据。优化MySQL是提升系统性能、减少资源消耗和提高响应速度的关键。...通过这些方法,你可以有效地提升MySQL数据库的运行效率和整体性能。
《MySQL数据库巡检手册》是一本专注于MySQL数据库管理和维护的专业指南。这本手册旨在帮助数据库管理员(DBA)以及IT专业人员系统地进行MySQL数据库的日常检查与优化工作,确保数据库系统的稳定、高效运行。MySQL...
通过上述实验内容的学习和实践,学生能够系统地掌握MySQL数据库中数据字典、表、索引和视图的基本操作方法,这对于日后进行数据库管理和维护工作具有重要意义。此外,实验还强调了理论知识与实际操作相结合的重要性...
MySQL数据库是一种广泛使用的开源关系型数据库管理系统,以其高效、可靠和易于学习的特性深受开发者喜爱。本教程“逐步精通MySQL数据库”旨在帮助初学者从零基础逐渐晋升为高级用户,全面掌握MySQL的核心技术和实践...
### MySQL 数据库优化详解 #### 一、MySQL优化概述 MySQL作为一款广泛使用的开源关系型数据库管理系统,在实际应用中,其性能表现对于整个系统的稳定性和响应速度至关重要。MySQL的优化可以分为多个方面,包括硬件...
MySQL数据库是世界上最受欢迎的开源关系型数据库管理系统之一,由Oracle公司拥有并维护。它以其高效、稳定和易于管理的特点在各种规模的企业和项目中得到广泛应用。在这个名为"Mysql数据库文件.zip"的压缩包中,包含...
在使用MySQL的过程中,我们经常会遇到一个名为`information_schema`的数据库。这个数据库在MySQL安装时自动生成,并且对于理解和管理MySQL系统具有重要作用。本文将详细介绍`information_schema`的功能、结构以及...
优化是一个复杂的任务,本文描述 MySQL 相关的数据库设计和查询优化、服务器端优化、存储引擎优化。 数据库设计和查询优化 在 MySQL 性能优化中,首先要考虑的就是 Database Schema 设计,这一点是非常重要的。一...
MySQL数据库设计与应用习题参考答案及操作题源代码 本资源为《MySQL数据库设计与应用》习题参考答案及...本资源涵盖了MySQL数据库设计与应用的多个方面,为读者提供了学习和掌握MySQL数据库的设计、应用和管理的机会。
MySQL数据库5.5版是MySQL关系型数据库管理系统的一个重要里程碑,它在5.x系列中提供了许多增强的功能和优化,旨在提高性能、稳定性和安全性。在这个版本中,MySQL致力于提供更强大的企业级数据库解决方案,同时也...