高性能MySQL:字符串类型(1)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高性能MySQL:字符串类型(1)相关的知识,希望对你有一定的参考价值。

参考技术A

   字符串类型( )

  mysql 支持多种字符串类型 每种类型还有很多变种 这些数据类型在 和 版本发生了很大的变化 使得情况更加复杂 从MySQL 开始 每个字符串列可以定义自己的字符集和排序规则 或者说校对规则(collation)(更多关于这个主题的信息请参考第 章) 这些东西会很大程度上影响性能

   VARCHAR 和CHAR 类型

  VARCHAR 和CHAR 是两种最主要的字符串类型 不幸的是 很难精确地解释这些值是怎么存储在磁盘和内存中的 因为这跟存储引擎的具体实现有关 下面的描述假设使用的存储引擎是InnoDB 和/ 或者MyISAM 如果使用的不是这两种存储引擎 请参考所使用的存储引擎的文档

  先看看VARCHAR 和CHAR 值通常在磁盘上怎么存储 请注意 存储引擎存储CHAR 或者VARCHAR 值的方式在内存中和在磁盘上可能不一样 所以MySQL 服务器从存储引擎读出的值可能需要转换为另一种存储格式 下面是关于两种类型的一些比较

   VARCHAR

  VARCHAR 类型用于存储可变长字符串 是最常见的字符串数据类型 它比定长类型更节省空间 因为它仅使用必要的空间(例如 越短的字符串使用越少的空间) 有一种情况例外 如果MySQL 表使用ROW_FORMAT=FIXED 创建的话 每一行都会使用定长存储 这会很浪费空间

  VARCHAR 需要使用 或 个额外字节记录字符串的长度 如果列的最大长度小于或等于 字节 则只使用 个字节表示 否则使用 个字节 假设采用latin 字符集 一个VARCHAR( ) 的列需要 个字节的存储空间 VARCHAR( ) 的列则需要 个字节 因为需要 个字节存储长度信息

  VARCHAR 节省了存储空间 所以对性能也有帮助 但是 由于行是变长的 在UPDATE 时可能使行变得比原来更长 这就导致需要做额外的工作 如果一个行占用的空间增长 并且在页内没有更多的空间可以存储 在这种情况下 不同的存储引擎的处理方式是不一样的 例如 MyISAM 会将行拆成不同的片段存储 InnoDB则需要分裂页来使行可以放进页内 其他一些存储引擎也许从不在原数据位置更新数据

  下面这些情况下使用VARCHAR 是合适的 字符串列的最大长度比平均长度大很多 列的更新很少 所以碎片不是问题 使用了像UTF 这样复杂的字符集 每个字符都使用不同的字节数进行存储

  在 或者更高版本 MySQL 在存储和检索时会保留末尾空格 但在 或更老的版本 MySQL 会剔除末尾空格

  InnoDB 则更灵活 它可以把过长的VARCHAR 存储为BLOB 我们稍后讨论这个问题

   CHAR

  CHAR 类型是定长的 MySQL 总是根据定义的字符串长度分配足够的空间 当存储CHAR 值时 MySQL 会删除所有的末尾空格(在MySQL 和更老版本中VARCHAR也是这样实现的 也就是说这些版本中CHAR 和VARCHAR 在逻辑上是一样的 区别只是在存储格式上) CHAR 值会根据需要采用空格进行填充以方便比较

  CHAR 适合存储很短的字符串 或者所有值都接近同一个长度 例如 CHAR 非常适合存储密码的MD 值 因为这是一个定长的值 对于经常变更的数据 CHAR 也比VARCHAR 更好 因为定长的CHAR 类型不容易产生碎片 对于非常短的列 CHAR 比VARCHAR 在存储空间上也更有效率 例如用CHAR( ) 来存储只有Y 和N 的值 如果采用单字节字符集注 只需要一个字节 但是VARCHAR( ) 却需要两个字节 因为还有一个记录长度的额外字节

  CHAR 类型的这些行为可能有一点难以理解 下面通过一个具体的例子来说明 首先 我们创建一张只有一个CHAR( ) 字段的表并且往里面插入一些值

  当检索这些值的时候 会发现string 末尾的空格被截断了

  如果用VARCHAR( ) 字段存储相同的值 可以得到如下结果

  数据如何存储取决于存储引擎 并非所有的存储引擎都会按照相同的方式处理定长和变长的字符串 Memory 引擎只支持定长的行 即使有变长字段也会根据最大长度分配最大空间 不过 填充和截取空格的行为在不同存储引擎都是一样的 因为这是在MySQL 服务器层进行处理的

       返回目录 高性能MySQL

       编辑推荐

       ASP NET MVC 框架揭秘

       Oracle索引技术

       ASP NET开发培训视频教程

lishixinzhi/Article/program/MySQL/201311/29687

高性能MySql系列-Schema与数据类型优化

最佳实践

1.越简单的类型越好
比如整型比字符串型好,因为字符的排序规则、校对规则更复杂。
2.尽量使用MySql内置的类型
比如用datetime存储日期,不要用字符串。
用整型存储IP地址,不要用字符串。因为IP地址xxx.xxx.xxx.xxx实际上底层是32位无符号整数,之所以表示为小数点的形式是为了方便阅读。所以应该使用整型来存储IP地址,Mysql也提供了INET_ATON()和INET_NTOA()在这2种表示形式间转换。
3.列长度越小越好
在存得下的前提下,长度越小越好。因为列长度越小,所需要的CPU、内存、磁盘空间就越少。
4.尽量避免null
通常情况下最好指定列为NOT NULL,除非真的需要NULL值。因为如果列中包含NULL值,对MySql来说更难优化,原因是可为NULL的列会使得索引、值比较都更加复杂。当可为NULL的列被索引时,每个索引记录都需要一个额外的字节来存储。所以在设计表时,如果希望给某列加索引,最好限定这列是NOT NULL的。
5.主键列最好选择整型
整型作为主键的优点是很快,并且方便AUTO_INCREMENT。
如果用字符串类型作为主键,它们很耗空间,并且性能也比整型慢。如果使用UUID作为主键,可以将“-”去掉之后再存储。Mysql提供了UNHEX()函数将UUID值转换为16字节的整数,并且也提供了HEX()重新格式化为16进制的UUID值。
6.计数器表尽量避免只有一行数据
当计数器表(如网站点击次数)只有一行数据时,会导致大量线程阻塞在这个行锁上,可以设计多行数据,每行都有个计数器,客户端请求更新计数器时,可以随机选择某行计数器进行更新,大大提升计数器表的并发性能。在查询总计数器时,只需SUM(count)即可。

以上是关于高性能MySQL:字符串类型(1)的主要内容,如果未能解决你的问题,请参考以下文章

高性能MySQL:字符串类型(2)

高性能MySql系列-Schema与数据类型优化

MYSQL性能调优07_MySQL数据类型选择数值类型日期和时间字符串

MySQL高性能

mysql中的字符串类型数据索引优化

MySQL性能优化2---数据类型和实例的优化