反范式的设计可以加快某些类型的查询,但也可能是的另一些类型的查询变慢.添加计数表和汇总表是一种很好的优化查询的方式.
1 选择合适的数据类型
通常原则是:
- 更小的通常更好:一般情况下应该尽量使用可以正确存储数据的最小数据类型.更小的数据类型通常更快,因为他们占用很少的磁盘,内存和cpu缓存,在处理的时候需要的cpu周期也更少.
- 简单就好:简单数据类型的操作通常用更少的cpu周期.比如整数比字符操作代价低,因为字符集和校对规则使得字符比整形更复杂.比如,mysql使用內建类型来存储时间和日期,而不是使用字符串.另外应该用整形存储ip地址
- 尽量避免 NULL:通常情况下最好指定列为
NOT NULL
,如果查询中包含可为NULL
的列,对mysql来说更难优化,因为NULL
的列使索引,索引统计和值都比较复杂,而且可能需要更多的存储空间.但是把NULL
改为NOT NULL
带来的性能提升比较少.
1.1 整数类型
有两种类型的数字:整数和实数,如果存储整数可以使用TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT,分别对应8,16,24,32,64位存储空间.
加上UNSIGNED属性,表示不允许负值,也就是无符号整数.有符号整数和无符号整数具有相同的性能和相同的存储空间.
Mysql中整数计算一般使用64位的BIGINT整数,即使在32位环境下也是使用64位整数.
类型后面的括号,如INT(8)
表示显示为位数,和存储无关.
1.2 实数类型
实数是带有小数部分的数字,由DECIMAL,FLOAT,DOUBLE,三种
其中DECIMAL可以存储比BIGINT更大的整数.
FLOAT和DOUBLE都支持标准的浮点运算(近似计算).分别使用4,8字节存储
DECIMAL类型用于存储精确小数.cpu不支持DECIMAL的直接计算,因此服务器自身实现了DECIMAL的高精度计算.DECIMAL在存储的时候,每4个字节存储9个数字.小数点单独占用一个数字.最多支持65个数字.
实数类型在定义的时候可以是DECIMAL(12,5)
,表示,总长12位,小数点后5位.
1.3 字符串类型
1.3.1 VARCHAR和CHAR
VARCHAR和CHAR是两种最要的字符串类型.其存储方式和存储引擎有关.当在定义的时候加上括号char(3)
表示最大存储3个字符,而不是字节.需要占据多少空间,需要根据字符集来确定
varchar存储可变长字符串,是最常见的字符串类型.比定长的char更加节省空间.varchar使用1或是2个额外的字节记录字符串长度.节省了存储空间,对性能也有帮助,但是当修改后字符串比原来更长的时候,需要分配额外的空间.具体的不同存储引擎不同.因为有了长度记录,因此最后的\0
不会被删除
char类型是定长的,根据定义直接分配指定大小的空间,使用\0
来记录字符串的结尾,因此结尾的\0
会被删除.
1.3.2 BINARY和VARBINARY
存储二进制形式的字符串.二进制字符串比字符串更快.
1.3.3 BLOG和TEXT类型
BLOG和TEXT是位存储很大的数据而设计的字符串数据类型,分别是采用二进制和字符串形式存储.
其有:TINYBLOG,SMALLTEXT,TEXT,MEDIUMTEXT,LONGTEXT和TINYBLOG,SMALBLOG,BLOG,MEDIUMBLOG,LONGBLOG.
1.3.4 枚举类型ENUM
在某些列,其值是固定的时候,可以使用美剧类型,mysql内部会将枚举类型的每个值在列表中保存为整数,并且建立数字-字符串映射的查找表.
但是扩展的时候不方便.
SET``(``‘value1‘``,``‘value2‘``,...)
一个集合。字符串对象可以有零个或多个值,每个值必须来自列值‘value1‘,‘value2‘,...SET列最多可以有64个成员。SET值在内部用整数表示。SET是一个字符串对象,可以有零或多个值,其值来自表创建时规定的允许的一列值。指定包括多个SET成员的SET列值时各成员之间用逗号(‘,’)间隔开。这样SET成员值本身不能包含逗号。
SET最多可以有64个不同的成员。对于指定为SET(‘a‘,‘b‘,‘c‘,‘d‘)的列,成员有下面的十进制和二进制值:
SET成员 | 十进制值 | 二进制值 |
---|---|---|
‘a‘ | 1 | 0001 |
‘b‘ | 2 | 0010 |
‘c‘ | 4 | 0100 |
‘d‘ | 8 | 1000 |
如果你为该列分配一个值9,其二进制形式为1001,因此第1个和第4个SET值成员‘a‘和‘d‘被选择,结果值为?‘a,d‘。
1.4 日期和时间类型
mysql能存储的最小时间粒度为秒.但是可以使用微妙级别进行临时计算.
DATE日期。支持的范围为‘1000-01-01‘到‘9999-12-31‘。MySQL以‘YYYY-MM-DD‘格式显示DATE值,但允许使用字符串或数字为DATE列分配值。
DATETIME日期和时间的组合。支持的范围是‘1000-01-01 00:00:00‘到‘9999-12-31 23:59:59‘。MySQL以‘YYYY-MM-DD HH:MM:SS‘格式显示DATETIME值,但允许使用字符串或数字为DATETIME列分配值。
TIMESTAMP``[(M)]时间戳。范围是‘1970-01-01 00:00:00‘到2037年。TIMESTAMP列用于INSERT或UPDATE操作时记录日期和时间。如果你不分配一个值,表中的第一个TIMESTAMP列自动设置为最近操作的日期和时间。也可以通过分配一个NULL值,将TIMESTAMP列设置为当前的日期和时间。TIMESTAMP值返回后显示为‘YYYY-MM-DD HH:MM:SS‘格式的字符串,显示宽度固定为19个字符。如果想要获得数字值,应在TIMESTAMP 列添加+0。
可以使用任何常见格式指定DATETIME、DATE和TIMESTAMP值:
- ‘YYYY-MM-DD HH:MM:SS‘或‘YY-MM-DD HH:MM:SS‘格式的字符串。允许“不严格”语法:任何标点符都可以用做日期部分或时间部分之间的间割符。例如,‘98-12-31 11:30:45‘、‘98.12.31 11+30+45‘、‘98/12/31 11*30*45‘和‘[email protected]@31 11^30^45‘是等价的。
- ‘YYYY-MM-DD‘或‘YY-MM-DD‘格式的字符串。这里也允许使用“不严格的”语法。例如,‘98-12-31‘、‘98.12.31‘、‘98/12/31‘和‘[email protected]@31‘是等价的。
- ‘YYYYMMDDHHMMSS‘或‘YYMMDDHHMMSS‘格式的没有间割符的字符串,假定字符串对于日期类型是有意义的。例如,‘19970523091528‘和‘970523091528‘被解释为‘1997-05-23 09:15:28‘,但‘971122129015‘是不合法的(它有一个没有意义的分钟部分),将变为‘0000-00-00 00:00:00‘。
- ‘YYYYMMDD‘或‘YYMMDD‘格式的没有间割符的字符串,假定字符串对于日期类型是有意义的。例如,‘19970523‘和‘970523‘被解释为 ‘1997-05-23‘,但‘971332‘是不合法的(它有一个没有意义的月和日部分),将变为‘0000-00-00‘。
- YYYYMMDDHHMMSS或YYMMDDHHMMSS格式的数字,假定数字对于日期类型是有意义的。例如,19830905132800和830905132800被解释为 ‘1983-09-05 13:28:00‘。
- YYYYMMDD或YYMMDD格式的数字,假定数字对于日期类型是有意义的。例如,19830905和830905被解释为‘1983-09-05‘
- 函数返回的结果,其值适合DATETIME、DATE或者TIMESTAMP上下文,例如NOW()或CURRENT_DATE。TIME
无效DATETIME、DATE或者TIMESTAMP值被转换为相应类型的“零”值(‘0000-00-00 00:00:00‘、‘0000-00-00‘或者00000000000000)。
列类型 | 零值 |
---|---|
DATETIME | ‘0000-00-00 00:00:00‘ |
DATE | ‘0000-00-00‘ |
TIMESTAMP | 00000000000000 |
TIME | ‘00:00:00‘ |
YEAR | 0000 |
无效DATETIME、DATE或者TIMESTAMP值被转换为相应类型的“零”值(‘0000-00-00 00:00:00‘、‘0000-00-00‘或者00000000000000)。
包括日期部分间割符的字符串值,如果日和月的值小于10,不需要指定两位数。‘1979-6-9‘与‘1979-06-09‘是相同的
数字值应为6、8、12或者14位长。如果一个数值是8或14位长,则假定为YYYYMMDD或YYYYMMDDHHMMSS格式,前4位数表示年。如果数字 是6或12位长,则假定为YYMMDD或YYMMDDHHMMSS格式,前2位数表示年。其它数字被解释为仿佛用零填充到了最近的长度。
用DEFAULT CURRENT_TIMESTAMP和ON UPDATE CURRENT_TIMESTAMP子句,列为默认值使用当前的时间戳,并且自动更新。
时间。范围是‘-838:59:59‘到‘838:59:59‘。MySQL以‘HH:MM:SS‘格式显示TIME值,但允许使用字符串或数字为TIME列分配值。
YEAR``[(2|4)]两位或四位格式的年。默认是四位格式。在四位格式中,允许的值是1901到2155和0000。在两位格式中,允许的值是70到69,表示从1970年到2069年。MySQL以YYYY 格式显示YEAR值,但允许使用字符串或数字为YEAR列分配值。00-69范围的年值转换为2000-2069,70-99范围的年值转换为1970-1999。
如果没有特殊要求外,通常尽量使用TIMESTAMP因为比DTAETIME更加节省空间和高效.
1.5 位数据类型
BIT
1.5 记录的标识符
标识列选择的选择一般选择位整数类型.
2 表设计
3 范式和反范式
在范式化的数据库中,每个事实数据只会出现一次,而在反范式化的数据库中,信息是冗余的,一个事实数据被存储在不同表中.
3.1 范式的优点和缺点
范式化的优点在于:
- 范式化的更新操作通常比反范式化要快,因为反范式话的数据有多份,在修改的时候,需要全部修改,但是读取的时候反范式化读取可能更快
- 数据符合范式化的时候,没有或是只有少数的重复数据,那么修改会更快
- 范式化的表通常跟小,可以更好的放在内存中
范式化的缺点,通常是在查询的时候需要关联,稍微复杂的查询语句在符合范式化的表上都至少需要一次关联.
3.2 反范式化的有点和缺点
反范式化的表,数据都在一张表中,因此能够很好的避免关联,读取数据更加快速.
3.3 混用范式化和反范式化
范式化和反范式化的表都各有优劣.因此在实际应用中经常是混用的.
最常见的反范式化数据的方法是复制或是缓存,在不同的表中存储相同的特定列.
4 缓存表和汇总表
提升性能的方法之一是缓存,在数据库中,可以创建一张完全独立的汇总表或是汇总表.这张表中,保存可以直接被查询的数据,不需要关联其他表,但是这张表中的数据可能不是实时更新的.
4.1 物化视图
物化视图是原先计算并且存储在磁盘上的表,然后通过各种策略更新.mysql不支持原生的物化视图,可以使用开源工具Flexviews.
跳
4.2 计数器表
如果在表中保存计数器,则更新计数器的时候会遇到并发的情况.
可以使用建立多个记录,每次更新的时候随机更新一条记录.
一般计数会采用非关系型数据库,定时刷新回mysql
5 加快ALTER TABLE操作速度
ALTER TABLE
操作表,的时候性能比较低.mysql执行大部分修改表结构的方式是用新的结构创建一个空表,然后从就表中查询所有数据,插入新表,然后删除旧表.这个操作需要花费的时间很长.因此ALTER TABLE
操作会导致mysql服务中断.解决方法有两种:
- 主备服务器之间,每次更新一台.
- 手动创建一张表,然后复制,删除原表,改名,这种形式来改变表结构
不是所有的ALTER TABLE
操作都会引起表重建.
5.1 只修改.frm文件
当修改表的列的默认值的时候,直接使用ALTER CLUMN
则只会修改.frm文件,不涉及到数据.
例如:
- 移除(不是增加),一个列的
AUTO_INCREMENT
属性 - 移除默认值
- 增加,移除更改
ENUM
,SET
的值
替换.frm
文件的过称为:
- 创建一张拥有相同结构的空表,进行需要的修改
- 执行
FLUSH TABLES WITH READ LOCK
,关闭所有正在使用的表,并且进制任何表被打开 - 替换
.frm
文件 - 执行
UNLOCK TABLES
5.2 快速创建MyISAM索引
跳
原文地址:https://www.cnblogs.com/perfy576/p/9170712.html