tinyint 1字节
int 4字节(0,4 294 967 295)
bigint 8字节
char(n) n字节
一,存储空间比较
int类型因为最大值限制不能够存储手机号,能选择bigint和char类型,如果单纯考虑存储空间bigint更合适,那么10亿条数据能节省多少空间哪?
1000000000 * 4 字节 = 4000000000 字节
4000000000 字节/1024 = 396250 K
396250 K / 1024 = 3814.69 MB
3814.69 MB /1024 = 3.72 G
二,至于查询效率,看实验结果
2.1 创建表
#创建 bigint 类型表
CREATE TABLE `phone_bigint` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`phone` bigint(11) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
#创建 char 类型
CREATE TABLE `phone_char` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`phone` char(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
2.2 创建存储过程
#创建存储过程 CREATE DEFINER=`root`@`localhost` PROCEDURE `insertphonebigint`(IN `string` varchar(400))
BEGIN
DECLARE i INT;
DECLARE j INT;
DECLARE y INT;
DECLARE pre CHAR(3);
DECLARE sqlstr TEXT(30000);
DECLARE phone CHAR(11);
SET i = 1;
while i < 92 do
SET pre = substring(string, i, 3);
set j = 1;
while j < 3225 do
set y=1;
set sqlstr = 'insert into phone_bigint(phone) VALUES';
while y < 1001 do
set phone = CONCAT(pre, (10000000 + j*1000 + y));
IF y > 1 THEN
set sqlstr = CONCAT(sqlstr, ',' , '(', phone, ')');
ELSE
set sqlstr = CONCAT(sqlstr, '(', phone, ')');
END IF;
SET y = y+1;
end while;
set sqlstr = CONCAT(sqlstr, ';');
set @execsql = sqlstr;
PREPARE stmt from @execsql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
set j = j+1;
end while;
SET i = i+3;
end while;
END
2.3 生成数据
# bigint 表生成数据 (总数据:99944000)
CALL insertphonebigint('134135136137138139147150151152157158159182183188178187130131132145175133153180181189177173149');
#复制数据
Insert into phone_char(phone) select phone from phone_bigint;
Insert into phone_tinyint(pre,phone) SELECT left(phone,3),right(phone,8) from phone_char;
2.4 在没有索引的情况比较
2.4.1 文件大小
表名 | 索引长度 | 数据长度 |
phone_bigint | 978.14 MB (1,025,657,856) | 1.21 GB (1,299,272,000) |
phone_char | 978.14 MB (1,025,657,856) | 3.54 GB (3,797,872,000) |
2.4.2 查询效率
EXPLAIN select * from phone_char where phone = '15910000002';
+----+-------------+------------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+------------+------------+------+---------------+------+---------+------+----------+----------+-------------+
| 1 | SIMPLE | phone_char | NULL | ALL | NULL | NULL | NULL | NULL | 99944000 | 10.00 | Using where |
+----+-------------+------------+------------+------+---------------+------+---------+------+----------+----------+-------------+
select * from phone_char where phone = '15910000002';
用时:39.12 sec
select * from phone_bigint where phone = 15910000002;
用时:11.369s
2.5 索引后的情况比较
2.5.1 文件大小
表名 | 索引长度 | 数据长度 |
phone_bigint | 2.29 GB (2,454,575,104) | 1.21 GB (1,299,272,000) |
phone_char | 2.24 GB (2,400,433,152) | 3.54 GB (3,797,872,000) |
2.5.2 查询效率
2.6 小结
精准查询时,bigint类型的key_len值较小,所以较优。
但在实际应用中可能会有模糊查询[like '159%'],数值是不支持模糊查询的,这时索引会失效。char 类型优势明显。
所以具体选择时不能只考虑一方面,要综合考虑。
三,其它方案
如果只是考虑存储方面,还有另一个办法,就是将手机号拆开,折成两个字段 一个字段tinyint类型存前3位,另一个int类型存后8位。
优点:这样一个手机号才占5字节。两个字段建立联合索引,查询速度也很快。
缺点:查询时需要额外的处理。
发表评论 取消回复