• MySQL 基础--字符类型


    ##=====================================================================================##

    MySQL支持的字符类型:

    类型大小用途
    CHAR 0-255字节 定长字符串
    VARCHAR 0-65535 字节 变长字符串
    TINYBLOB 0-255字节 不超过 255 个字符的二进制字符串
    TINYTEXT 0-255字节 短文本字符串
    BLOB 0-65 535字节 二进制形式的长文本数据
    TEXT 0-65 535字节 长文本数据
    MEDIUMBLOB 0-16 777 215字节 二进制形式的中等长度文本数据
    MEDIUMTEXT 0-16 777 215字节 中等长度文本数据
    LONGBLOB 0-4 294 967 295字节 二进制形式的极大文本数据
    LONGTEXT 0-4 294 967 295字节 极大文本数据

     ##=====================================================================================##

    CHAR(N)和VARCHAR(N)中N的问题

    在MySQL 4.1版本前,CHAR(N)和VARCHAR(N)中的N指的是字节长度。
    从MYSQL 4.1版本后,CHAR(N)和VARCHAR(N)中的N指的是字符的长度。

     ##=====================================================================================##

    字节长度和字符长度

    使用length(str)来查看str占用的字节数
    使用char_length(str)表示str占用的字符数

    对于多字节的字符编码来说,不同字符的编码长度不一样,如对于UTF来说,‘a’需要一个字节来存放,而对于中文‘你’则需要3字节来存放,
    因此对于使用UTF8来存放的CHAR(N) 来说,最低使用N字节点空间,最高使用3N字节的空间,因此存储引擎在内部将CHAR类型视为变长字符类型来处理。

    在MySQL中定义行的长度不能超过65535字节,因此会根据数据的字符集来限制VARCHAR(N)的N值,如当使用UTF8编码时,每个字符占用3个字节,一行的最大长度只能存放(65535-3)/3=21844个字符(在不考虑其他额外记录信息情况下),当创建表时指定的N超过最大值时,会将VARCHAR(N)类型装换为mediumtext类型。

    DROP TABLE IF EXISTS tb1007;
    DROP TABLE IF EXISTS tb1008;
    CREATE TABLE `tb1007` (
      `id` INT (11) NOT NULL AUTO_INCREMENT,
      `c1` VARCHAR (21800) DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
    CREATE TABLE `tb1008` (
      `id` INT (11) NOT NULL AUTO_INCREMENT,
      `c1` VARCHAR (21900) DEFAULT NULL,
      PRIMARY KEY (`id`)
    );
    SHOW CREATE TABLE tb1007; SHOW
    CREATE TABLE tb1008; 输出: CREATE TABLE `tb1007` ( `id` int(11) NOT NULL AUTO_INCREMENT, `c1` varchar(21800) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 CREATE TABLE `tb1008` ( `id` int(11) NOT NULL AUTO_INCREMENT, `c1` mediumtext, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8

     

    PS1:对于VARCHAR类型,除包括字符数据需要的空间外,还额外需要1或2个字节来记录字符串的长度,对于字符串长度小于或等于255字节时使用1个字节表示,大于255字节的字符串的使用2字节表示。

    PS2:当MySQL表使用ROW_FORMAT=FIXED时,对于定义VARCHAR类型的列会使用定长存储。

     ##=====================================================================================##

    VARCHAR类型字符串空格问题
    在MySQL 4.1及其之前版本,MySQL会截取字符串尾部的空格,
    在MySQL 5.0及之后版本中,MySQL会保留字符串结尾的空格。

    尾部空格是否截断是在MySQL Server层进行处理,与存储引擎层无关。
    在MySQL 5.6版本测试如下:

    create table tb002(c1 varchar(200));
    insert into tb002(c1)values('   abc   ');
    select concat('123',c1,'456') from tb002;
    +------------------------+
    | concat('123',c1,'456') |
    +------------------------+
    | 123   abc   456        |
    +------------------------+

    ##=====================================================================================##

    CHAR类型字符串空格问题
    无论在MySQL 4.1版本之前还是之后,对于CHAR类型字符串,在检索时总会删除所有的末尾空格。
    在MySQL 5.6版本测试如下:

    drop table tb002;
    create table tb002(c1 char(10));
    insert into tb002(c1)values('   abc   ');
    select concat('123',c1,'456') from tb002;
    +------------------------+
    | concat('123',c1,'456') |
    +------------------------+
    | 123   abc456           |
    +------------------------+

    ##=====================================================================================##
    VARCHAR和CHAR效率问题
    1、当存储的所有数据都接近同一最大长度时,使用CHAR存放效率更高
    2、当存储的数据长度差距较大,尤其少量数据长度较大时,使用CHAR存放会浪费较多的存储空间,使用VARCHAR存放更为合理
    3、无论使用VARCHAR还是使用CHAR,都应遵守最小存储空间原则,避免将N设置过大造成性能问题。

    ##=====================================================================================##
    其他字符问题
    1、对于BINARY和VARBINARY类型,在存储时使用字节码来存放,在比较时依次按照每一个字节来对比
    2、BINARY类型采用(零字节)而不是空格来进行填充
    3、数据如何存储取决于存储引擎,Memory存储引擎只支持定长列,且Memroy存储引擎不支持BLOB和TEXT类型。
    4、字符串填充和截取空格的行为在MySQL服务器层进行处理,因此对于所有存储引擎都一样

    ##=====================================================================================##
    限制VARCHAR(N)中N值大小的意义:

    对于不同存储引擎,在存放VARCHAR(N)类型数据时采用不同的存储方式,对于Innodb存储引擎,使用额外来1-2byte空间来存放变长列的数据长度,因此数据使用的存储空间与N值无明显关系,N值过大也不会导致数据占用过多的磁盘空间。
    当数据从存储引擎读取到MySQL内存中时,数据在存储引擎中存放方式和在内存中的存放方式不同,存储引擎负责将数据进行转换放入至MySQL内存,而MySQL通常会分配固定大小的内存块来存放数据,因此对于VARCHAR(N)类型数据,当N值越大时,可能会导致MySQL分配越多的内存来存放数据,尤其在使用内存临时表进行排序或操作时,N值过大可能会导致内存临时表超过参数tmp_table_size阀值而升级为磁盘临时表,引发严重的性能问题。

    PS1:由于测试过程中无法使用profile工具查看语句使用的内存信息,对于两个数据相同但VARCHAR(N)列N值差异较大的两个表做相同SQL查询发现性能没有太大差异,生成的临时表消耗的IO也接近,无法明确验证上述观点。

  • 相关阅读:
    0113-06-侯舒舒(作业-复盘分析)
    0113-06-侯舒舒(日报)
    总结
    0108-06-侯舒舒(日报)
    cobalt strike插件
    关于python安装后更新的一些问题
    常用dos命令
    curl命令用法
    2020/1/16
    2020/1/15
  • 原文地址:https://www.cnblogs.com/TeyGao/p/9113736.html
Copyright © 2020-2023  润新知