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字节。两个字段建立联合索引,查询速度也很快。
    缺点:查询时需要额外的处理。

点赞(4077) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部