在数据库设计的时候会遇到很多只需要0、1、2这种固定几个值的状态字段,基本上都建议设置为只占一字节的tinyint类型,有些觉得char(1)是一样,毕竟char(1)存储数字和字母时一个字符也只是占一个字节。
mysql是用c++写的,而在c++中字符类型是存放对应ascii码的二进制到存储空间,而整型数字是直接存数字的二进制,虽然最终都是二进制存储,但是环节上有少许不同,同样在msyql查找时也会有所不同,下图摘自小白版c++教程《c++ primer plus》:
今天对tinyint和char(1)做了个简单测试,分表建两个表t1、t2,结构如下:
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`_id` int(11) NOT NULL AUTO_INCREMENT,
`id` tinyint(4) DEFAULT NULL,
`title` text,
PRIMARY KEY (`_id`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2400096 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
mysql> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`_id` int(11) NOT NULL AUTO_INCREMENT,
`id` char(1) DEFAULT NULL,
`title` text,
PRIMARY KEY (`_id`),
KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2400096 DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
两个表唯一不同为id字段类型,总数据量都为2400096,id只有0、1、2三个,为了两个表的数据一样且磁盘上分布也一样,降低IO对测试的影响,分别加载的数据如下:
mysql> select id,count(*) from t1 group by id;
+------+----------+
| id | count(*) |
+------+----------+
| 0 | 1199998 |
| 1 | 1199998 |
| 2 | 99 |
+------+----------+
3 rows in set (0.55 sec)
mysql> select id,count(*) from t2 group by id;
+------+----------+
| id | count(*) |
+------+----------+
| 0 | 1199998 |
| 1 | 1199998 |
| 2 | 99 |
+------+----------+
3 rows in set (0.77 sec)
查看执行计划:
mysql> explain select _id from test.t2 where id='1';
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------+
| 1 | SIMPLE | t2 | ref | id | id | 4 | const | 1170900 | Using where; Using index |
+----+-------------+-------+------+---------------+------+---------+-------+---------+--------------------------+
1 row in set (0.00 sec)
mysql> explain select _id from test.t1 where id=1;
+----+-------------+-------+------+---------------+------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+---------+-------------+
| 1 | SIMPLE | t1 | ref | id | id | 2 | const | 1170601 | Using index |
+----+-------------+-------+------+---------------+------+---------+-------+---------+-------------+
1 row in set (0.00 sec)
两个表都使用了id索引,再看看information_schema.tables的信息是否和之前理解的存储字节大小是否有出入:
mysql> select DATA_LENGTH/1024/1024,INDEX_LENGTH/1024/1024,data_free from tables where table_name in ('t1','t2');
+-----------------------+------------------------+-----------+
| DATA_LENGTH/1024/1024 | INDEX_LENGTH/1024/1024 | data_free |
+-----------------------+------------------------+-----------+
| 310.81250000 | 27.56250000 | 0 |
| 313.81250000 | 29.56250000 | 0 |
+-----------------------+------------------------+-----------+
2 rows in set (0.00 sec)
两个表大小相差不多,确认char(1)和tinyint占字节数相同,现在直接看执行时间:
mysql> show profiles;
+----------+------------+---------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+---------------------------------------------------------------+
| 1 | 0.60804275 | select count(*) from (select _id from test.t1 where id=1) a |
| 2 | 0.59277575 | select count(*) from (select _id from test.t1 where id=1) a |
| 3 | 0.60398000 | select count(*) from (select _id from test.t1 where id=1) a |
| 4 | 0.69068025 | select count(*) from (select _id from test.t2 where id='1') a |
| 5 | 0.69654200 | select count(*) from (select _id from test.t2 where id='1') a |
| 6 | 0.67788800 | select count(*) from (select _id from test.t2 where id='1') a |
+----------+------------+---------------------------------------------------------------+
这样就很明显可以看出为char(1)字段的t2表查询时消耗时间偏多,如果几条几百条的情况根本看不出char(1)和tinyint的差别,毕竟现在CPU的效率是非常高的,这里测试的利用了id=1的数据,有1199998条,这样就可以看出点差别了!!虽然效率差别不是很大,为了生产环境统一以及提升QPS还是使用短小的整型更好.
DROP TABLE IF EXISTS `sys_area`;
CREATE TABLE `sys_area` (
`id`
int
(10) unsigned NOT NULL AUTO_INCREMENT,
`parent_id`
int
(10) unsigned NOT NULL DEFAULT '0' COMMENT '上级',
`area_name` var
char
(20) NOT NULL DEFAULT '' COMMENT '地名',
`level` var
char
(255) DEFAULT '1' COMMENT '层级 1省 2市 3区',
`area_code`
char
(12) DEFAULT '' COMMENT '编码',
`sort`
tiny
int
(3) unsigned DEFAULT '255' COMMENT '排序',
PRIMARY KEY (`id`) USING BTREE,
KEY `pid` (`parent_id`) USING BTREE
首先我们需要知道,
MySQL
支持多种类型,大致可以分为三类:数值、日期/时间和字符串类型。01数值类型包含所有标准SQL支持的数值数据类型。02日期和时间类型03字符串类型binary 和 varbinary 类似于 常用的
char
和 var
char
,不同的是它们包含二进制字符串而不要非二进制字符串。也就是说,它们包含字节字符串而不是字符字符串。这说明它们没有字符集,并且排序和比较基于...
做IsDeleted,Islock,State时,字段的数据类型选择一般有三种Bit,
char
,
tiny
int
,大于2个字节的类型我们暂时不考虑,这里以mssql为例。
数据大小:
Bit,
char
,
tiny
int
三种类型均占用一个字节
取值范围:
Bit——只能有两个值,0或1,插入大于1的数字默认转换成1,也就是true。
char
(1)——只能是单个字母。
tiny
int
——...
mysql
tiny
int
和
char
(1)
性能
对比在数据库设计的时候会遇到很多只需要0、1、2这种固定几个值的状态字段,基本上都建议设置为只占一字节的
tiny
int
类型,有些觉得
char
(1)是一样,毕竟
char
(1)存储数字和字母时一个字符也只是占一个字节
mysql
是用c++写的,而在c++中字符类型是存放对应ascii码的二进制到存储空间,而整型数字是直接存数字的二进制,虽然最终都是二进制存储...
参考别人的文档说明:
https://blog.csdn.net/yzj5208/article/details/81214780
tiny
int
(1) 在高数据量情况下比
char
(1) 要好,我选择
tiny
int
(3) ,如果用
tiny
int
(1)与
tiny
int
(3) 表示的范围是一样的,但是
tiny
int
(1) 在mybatis里面会被自动转换为 boolean类型的实体,会有些麻烦,我推荐使用
tiny
int
(3)
tiny
int
存储范围是-128到127,在这之间的数都是占用1个字节,8位
1.BIT[M]位字段類型,M表示每個值的位數,范圍從1到64,如果M被忽略,默認為12.
TINY
INT
[(M)] [UNSIGNED] [ZEROFILL]M默認為4,占1個字節很小的整數。帶符號的范圍是-128到127。無符號的范圍是0到255。3.BOOL,BOOLEAN是
TINY
INT
(1)的同義詞。zero值被視為假。非zero值視為真。4.SMALL
INT
[(M)] [UNSIG...
char
、var
char
属于字符串类型
1、
char
属于定长,能确切的知道列值的长度,也就是有多少个字符。当指定
char
(5)时,表示只能存5个字符,如5个英文‘a’,5个汉字‘我’,5个符号‘&’等等,超出部分会被截掉,不足部分会在字符串后面以空格补充,取出时去去掉后面的空格。占用5个字节。
2、var
char
属于不定长,当指定var
char
(5)时,表示只能存5个字符,如5...