数据类型
整数类型
类型 | 字节 | 有符号范围 | 无符号范围 |
TINYINT | 1 | -128~127 | 0~255 |
SMALLINT | 2 | -32768~32767 | 0~65535 |
MEDIUMINT | 3 | -8388608~8388607 | 0~16777215 |
INT | 4 | -2147483648~2147483647 | 0~4294967295 |
BIGINT | 8 | -263~2^63-1 | 0~2^64-1 |
有符号和无符号(UNSIGNED)的区别在于能否表示负数
有符号值可以表示负数,0以及正数
无符号值只能为0或正数
建表时候的int(M),这里的M表示整数类型的最大显示宽度。对于浮点和定点类型, M是可以存储的总位数(精度)。对于字符串类型, M是最大长度。
先简单创建一张表
可以看到这里的M为2,插入整数11和字符串1,插入成功
插入整数111和字符串1,插入成功
插入整数1111和字符串222,插入失败
原因就是M在整型和在字符类型中所代表的含义不一样,而整型的显示长度有什么用呢,它的用处在于用了零填充这个约束条件之后才能明显看出。
先添加一个字段以供测试:
然后插入数据:
浮点数类型和定点数类型
常用于存储精确的小数,M是总位数,D是小数点后的位数。小数点和(负数) -符号不计入 M。如果 D为0,则值没有小数点或小数部分。最大位数(M)为 65. 最大支持小数(D)为30.如果D省略,则默认值为0.如果M省略,则默认值为10。M的范围是1到65。D范围为0到30,且不得大于M。
浮点数发生插入值超出字段的精度范围后,采取四舍五入,存入。
float会发生精度问题,所以对于类似于货币对数据准确性要求比较高的,最好使用定点数(decimal)
字符串类型
- CHAR[(M)] 一个固定长度的字符串,在存储时始终用空格填充指定长度。 M表示以字符为单位的列长度。M的范围为0到255.如果M省略,则长度为1,存储时占用M个字节
- VARCHAR(M) 可变长度的字符串,M 表示字符的最大列长度,M的范围是0到65,535,存储时占用 L+1(L<=M,L为实际字符的长度)个字节
- TINYTEXT[(M)] 不能有默认值,占用L+1个字节,L<2^8
- TEXT[(M)] 不能有默认值,占用L+2个字节,L<2^16
- MEDIUMTEXT[(M)] 不能有默认值,占用L+3个字节,L<2^24
- LONGTEXT[(M)] 不能有默认值,占用L+4个字节,L<2^32
- ENUM(‘value1’,‘value2’,…) ENUM是一个字符串对象,其值从允许值列表中选择,它只能有一个值,从值列表中选择,最多可包含65,535个不同的元素
- SET(‘value1’,‘value2’,…) 字符串对象,该对象可以有零个或多个值,最多可包含64个不同的成员
char定长,存储效率不如varchar,对于短数据的查询优于varchar。因为在大数据量没有索引的情况下,mysql查询走的是主键创建的索引,通过主键查询,数据量大效率的瓶颈是磁盘的io,当数据量大的时候,char是固定长度,占用的磁盘空间较大,查询效率就降低。
- CHAR适合存储很短的字符串,或者所有值都接近同一个长度。例如,CHAR非常适合存储密码的MD5值,因为这是一个定长的值。对于经常变更的数据,CHAR也比VARCHAR更好,因为定长的CHAR类型不容易产生碎片。对于非常短的列,CHAR比VARCHAR在存储空间上也更有效率。例如用CHAR(1)来存储只有Y和N的值,如果采用单字节字符集只需要一个字节,但是VARCHAR(1)却需要两个字节,因为还有一个记录长度的额外字节。
- VARCHAR适用于字符串很长或者所要存储的字符串长短不一,差别很大;字符串列的最大长度比平均长度大得多;列的更新很少,所以碎片不是问题.
日期时间类型
- TIME 范围是’-838:59:59.000000’ 到’838:59:59.000000’
- DATE 支持的范围是 '1000-01-01’到 ‘9999-12-31’
- DATETIME 日期和时间组合。支持的范围是 '1000-01-01 00:00:00.000000’到 ‘9999-12-31 23:59:59.999999’。
- TIMESTAMP 时间戳。范围是’1970-01-01 00:00:01.000000’UTC到’2038-01-19 03:14:07.999999’UTC。
- YEAR 范围是 1901到2155
索引
索引是什么
数据库索引好比是一本书前面的目录,能加快数据库的查询速度。索引往往是存储在磁盘上的文件中的。我们通常所说的索引,包括聚集索引、覆盖索引、组合索引、前缀索引、唯一索引等,没有特别说明,默认都是使用B+树结构组织(多路搜索树,并不一定是二叉的)的索引。
索引的优势和劣势
优势
- 可以提高数据检索的效率,降低数据库的IO成本,类似于书的目录。
- 通过索引列对数据进行排序,降低数据排序的成本,降低了CPU的消耗。
- 被索引的列会自动进行排序,包括【单列索引】和【组合索引】,只是组合索引的排序要复杂一些。
- 如果按照索引列的顺序进行排序,对应order by语句来说,效率就会提高很多。
劣势
- 索引会占据磁盘空间
- 索引虽然会提高查询效率,但是会降低更新表的效率。比如每次对表进行增删改操作,MySQL不仅要保存数据,还有保存或者更新对应的索引文件。
索引类型
主键索引
一张表只能有一个主键索引,不允许重复,不允许为 NULL;
ALTER TABLE TableName ADD PRIMARY KEY(column_list);
普通索引
一张表可以创建多个普通索引,一个普通索引可以包含多个字段,允许数据重复,允许 NULL 值插入;
CREATE INDEX IndexName ON `TableName`(`字段名`(length));
# 或者
ALTER TABLE TableName ADD INDEX IndexName(`字段名`(length));
唯一索引
数据列不允许重复,允许为 NULL 值,一张表可有多个唯一索引,索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
CREATE UNIQUE INDEX IndexName ON `TableName`(`字段名`(length));
# 或者
ALTER TABLE TableName ADD UNIQUE (column_list);
全文索引
只能在文本类型CHAR,VARCHAR,TEXT类型字段上创建全文索引。字段长度比较大时,如果创建普通索引,在进行like模糊查询时效率比较低,这时可以创建全文索引。 MyISAM和InnoDB中都可以使用全文索引。
//建表的时候
FULLTEXT KEY keyname(colume1,colume2) // 创建联合全文索引列
//在已存在的表上创建
create fulltext index keyname on xxtable(colume1,colume2);
alter table xxtable add fulltext index keyname (colume1,colume2);
空间索引
在MySQL5.7之后开始支持,遵循OpenGIS几何数据模型规则。
前缀索引
在文本类型如CHAR,VARCHAR类列上创建索引时,可以指定索引列的长度,但是数值类型不能指定。
单列索引和组合索引
组合索引的使用,需要遵循最左前缀匹配原则(最左匹配原则)。一般情况下在条件允许的情况下使用组合索引替代多个单列索引使用。
索引的数据结构
MySQL的索引采用的是B+树的数据结构
索引的创建
- 在经常需要搜索的列上,可以加快搜索的速度
- 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构
- 在经常用在连接(JOIN)的列上,这些列主要是一外键,可以加快连接的速度
- 在经常需要根据范围(<,<=,=,>,>=,BETWEEN,IN)进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的
- 在经常需要排序(order by)的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;
- 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。
- 对于那些在查询中很少使用或者参考的列不应该创建索引。若列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
- 对于那些只有很少数据值或者重复值多的列也不应该增加索引。这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
- 对于那些定义为text, image和bit数据类型的列不应该增加索引。这些列的数据量要么相当大,要么取值很少。当该列修改性能要求远远高于检索性能时,不应该创建索引。(修改性能和检索性能是互相矛盾的)