字符串类型()
与CHAR 和VARCHAR 类似的类型还有BINARY 和VARBINARY它们存储的是二进制字符串二进制字符串跟常规字符串非常相似但是二进制字符串存储的是字节码而不是字符填充也不一样MySQL 填充BINARY 采用的是\(零字节)而不是空格在检索时也不会去掉填充值
当需要存储二进制数据并且希望MySQL 使用字节码而不是字符进行比较时这些类型是非常有用的二进制比较的优势并不仅仅体现在大小写敏感上MySQL 比较BINARY 字符串时每次按一个字节并且根据该字节的数值进行比较因此二进制比较比字符比较简单很多所以也就更快
慷慨是不明智的
使用VARCHAR() 和VARCHAR() 存储hello的空间开销是一样的那么使用更短的列有什么优势吗?
事实证明有很大的优势更大的列会消耗更多的内存因为MySQL 通常会分配固定大小的内存块来保存内部值尤其是使用内存临时表进行排序或操作时会特别糟糕在利用磁盘临时表进行排序时也同样糟糕
所以最好的策略是只分配真正需要的空间
BLOB 和TEXT 类型
BLOB 和TEXT 都是为存储很大的数据而设计的字符串数据类型分别采用二进制和字符方式存储
实际上它们分别属于两组不同的数据类型家族字符类型是TINYTEXTSMALLTEXTTEXTMEDIUMTEXTLONGTEXT ;对应的二进制类型是TINYBLOBSMALLBLOBBLOBMEDIUMBLOBLONGBLOBBLOB 是SMALLBLOB 的同义词TEXT 是SMALLTEXT 的同义词
与其他类型不同MySQL 把每个BLOB 和TEXT 值当作一个独立的对象处理存储引擎在存储时通常会做特殊处理当BLOB 和TEXT 值太大时InnoDB 会使用专门的外部
存储区域来进行存储此时每个值在行内需要 ~ 个字节存储一个指针然后在外部存储区域存储实际的值
BLOB 和TEXT 家族之间仅有的不同是BLOB 类型存储的是二进制数据没有排序规则或字符集而TEXT 类型有字符集和排序规则
MySQL 对BLOB 和TEXT 列进行排序与其他类型是不同的它只对每个列的最前max_sort_length 字节而不是整个字符串做排序如果只需要排序前面一小部分字符则可以减小max_sort_length 的配置或者使用ORDER BY SUSTRING(column length)
MySQL 不能将BLOB 和TEXT 列全部长度的字符串进行索引也不能使用这些索引消除排序(关于这个主题下一章会有更多的信息)
磁盘临时表和文件排序
因为Memory 引擎不支持BLOB 和TEXT 类型所以如果查询使用了BLOB 或TEXT列并且需要使用隐式临时表将不得不使用MyISAM 磁盘临时表即使只有几行数据也是如此(Percona Server 的Memory 引擎支持BLOB 和TEXT 类型但直到本书写作之际同样的场景下还是需要使用磁盘临时表)
这会导致严重的性能开销即使配置MySQL 将临时表存储在内存块设备上(RAMDisk)依然需要许多昂贵的系统调用
最好的解决方案是尽量避免使用BLOB 和TEXT 类型如果实在无法避免有一个技巧是在所有用到BLOB 字段的地方都使用SUBSTRING(column length) 将列值转换为字符串(在ORDER BY 子句中也适用)这样就可以使用内存临时表了但是要确保截取的子字符串足够短不会使临时表的大小超过max_heap_table_size 或tmp_table_size超过以后MySQL 会将内存临时表转换为MyISAM 磁盘临时表
最坏情况下的长度分配对于排序的时候也是一样的所以这一招对于内存中创建大临时表和文件排序以及在磁盘上创建大临时表和文件排序这两种情况都很有帮助例如假设有一个 万行的表占用几个GB 的磁盘空间其中有一个utf字符集的VARCHAR() 列每个字符最多使用 个字节最坏情况下需要 字节的空间如果在ORDER BY 中用到这个列并且查询扫描整个表为了排序就需要超过GB 的临时表
这三行数据实际存储为整数而不是字符串可以通过在数字上下文环境检索看到这个双重属性
返回目录高性能MySQL
编辑推荐
ASPNET MVC 框架揭秘
Oracle索引技术
ASP NET开发培训视频教程
数据仓库与数据挖掘培训视频教程