第章 Schema与数据类型优化
良好的逻辑设计和物理设计是高性能的基石应该根据系统将要执行的查询语句来设计schema这往往需要权衡各种因素例如反范式的设计可以加快某些类型的查询但同时可能使另一些类型的查询变慢比如添加计数表和汇总表是一种很好的优化查询的方式但这些表的维护成本可能会很高MySQL 独有的特性和实现细节对性能的影响也很大
本章和聚焦在索引优化的下一章覆盖了MySQL 特有的schema 设计方面的主题我们假设读者已经知道如何设计数据库所以本章既不会介绍如何入门数据库设计也不会讲解数据库设计方面的深入内容这一章关注的是MySQL 数据库的设计主要介绍的是MySQL 数据库设计与其他关系型数据库管理系统的区别如果需要学习数据库设计方面的基础知识建议阅读Clare Churcher 的《Beginning Database Design》(Apress出版社)一书
本章内容是为接下来的两个章节做铺垫在这三章中我们将讨论逻辑设计物理设计和查询执行以及它们之间的相互作用这既需要关注全局也需要专注细节还需要理解整个系统以便弄清楚各个部分如何相互影响如果在阅读完索引和查询优化章节后再回头来看这一章也许会发现本章很有用很多讨论的议题不能孤立地考虑
选择优化的数据类型
MySQL 支持的数据类型非常多选择正确的数据类型对于获得高性能至关重要不管存储哪种类型的数据下面几个简单的原则都有助于做出更好的选择
更小的通常更好
一般情况下应该尽量使用可以正确存储数据的最小数据类型更小的数据类型通常更快因为它们占用更少的磁盘内存和CPU 缓存并且处理时需要的CPU 周期也更少
但是要确保没有低估需要存储的值的范围因为在schema 中的多个地方增加数据类型的范围是一个非常耗时和痛苦的操作如果无法确定哪个数据类型是最好的就选择你认为不会超过范围的最小类型(如果系统不是很忙或者存储的数据量不多或者是在可以轻易修改设计的的早期阶段那之后修改数据类型也比较容易)
简单就好
简单数据类型的操作通常需要更少的CPU 周期例如整型比字符操作代价更低因为字符集和校对规则(排序规则)使字符比较比整型比较更复杂这里有两个例子一个是应该使用MySQL 内建的类型注 而不是字符串来存储日期和时间另外一个是应该用整型存储IP 地址稍后我们将专门讨论这个话题
尽量避免NULL
很多表都包含可为NULL(空值)的列即使应用程序并不需要保存NULL 也是如此这是因为可为NULL 是列的默认属性注通常情况下最好指定列为NOT NULL除非真的需要存储NULL 值
如果查询中包含可为NULL 的列对MySQL 来说更难优化因为可为NULL 的列使得索引索引统计和值比较都更复杂可为NULL 的列会使用更多的存储空间在MySQL 里也需要特殊处理当可为NULL 的列被索引时每个索引记录需要一个额外的字节在MyISAM 里甚至还可能导致固定大小的索引(例如只有一个整数列的索引)变成可变大小的索引
通常把可为NULL 的列改为NOT NULL 带来的性能提升比较小所以(调优时)没有必要首先在现有schema 中查找并修改掉这种情况除非确定这会导致问题但是如果计划在列上建索引就应该尽量避免设计成可为NULL 的列
当然也有例外例如值得一提的是InnoDB 使用单独的位(bit)存储NULL 值所以对于稀疏数据注 有很好的空间效率但这一点不适用于MyISAM
在为列选择数据类型时第一步需要确定合适的大类型数字字符串时间等这通常是很简单的但是我们会提到一些特殊的不是那么直观的案例
下一步是选择具体类型很多MySQL 的数据类型可以存储相同类型的数据只是存储的长度和范围不一样允许的精度不同或者需要的物理空间(磁盘和内存空间)不同相同大类型的不同子类型数据有时也有一些特殊的行为和属性
例如DATETIME 和TIMESAMP 列都可以存储相同类型的数据时间和日期精确到秒
然而TIMESTAMP 只使用DATETIME 一半的存储空间并且会根据时区变化具有特殊的自动更新能力另一方面TIMESTAMP 允许的时间范围要小得多有时候它的特殊能力会成为障碍
本章只讨论基本的数据类型MySQL 为了兼容性支持很多别名例如INTEGERBOOL以及NUMERIC它们都只是别名这些别名可能令人不解但不会影响性能如果建表时采用数据类型的别名然后用SHOW CREATE TABLE 检查会发现MySQL 报告的是基本类型而不是别名
返回目录高性能MySQL
编辑推荐
ASPNET MVC 框架揭秘
Oracle索引技术
ASP NET开发培训视频教程
数据仓库与数据挖掘培训视频教程