分类: Mysql/postgreSQL
2008-09-05 20:55:44
2.3 选择列的类型
上一节描述了各种可供选择的MySQL的列类型及其属性,以及它们可存储的各种值,所占用的存储空间等 等。但是在实际创建一个表时怎样决定用哪些类型呢?本节讨论在做出决定前应考虑的各种因素。最“常用”的列类型是串类型。可将任何数据存储为串,因为数和 日期都可以串的形式表示。但是为什么不将所有列都定义为串从而结束这里的讨论呢?让我们来看一个简单的例子。假定有一些看起来像数的值。可将它们表示为 串,但应该这样做吗?这样做会发生什么事?
有一桩事不可避免,那就是可能要使用更多的空间,因为较串来说,数的存储更为有效。我们可能 已经注意到,由于数和串处理方式的不同,查询结果也有所不同。例如,数的排序与串的排序就有所不同。数2 小于数11,但串“2”按字典顺序大于“ 11”。可用如下数值内容的列来搞清这个问题:
将零加到该列强制得出一个数值,但是这样合理吗?一般可能不合理。将该列作为数而不是串具有几个重要的含义。它对每个列值实施串到数的转换,这 是低效的。而且将该列的值转换为计算结果妨碍MySQL使用该列上的索引,降低了以后的查询速度。如果这些值一开始就是作为数值存储的,那么这些性能上的 降低都不会出现。采用一种表示而不用另一种的简单选择实际上并不简单,它在存储需求、查询效率以及处理性能等方面都会产生重要的影响。
前面的例子说明,在选择列类型时,有以下几个问题需要考虑:
■ 列中存储何种类型的值?这是一个显而易见的问题,但必须确定。可将任何类型的值表示为串,尤其当对数值使用更为合适的类型可能得到更好的性能时(日期和时 间值也是这样)。可见,对要处理的值的类型进行评估不一定是件微不足道的事,特别在数据是别人的数据时更是如此。如果正在为其他人建立一个表,搞清列中要 存储的值的类型极为重要,必须提足够多的问题以便得到作出决定的充足的信息。
■ 列值有特定的取值范围吗?如果它们是整数,它们总是非负值吗?如果这样,可采用UNSIGNED 类型。如果它们是串,总能从定长值集中选出它们吗?如果这样, ENUM或SET 是很合适的类型。在类型的取值范围与所用的存储量之间存在折衷。需有一个多“大”的类型?对于数,如果其取值范围有限,可以选择较小的类型,对取值范围几 乎无限的数,应该选择较大的类型。对于串,可以使它们短也可以使它们长,但如果希望存储的值只含不到10 个字符,就不应该选用CHAR( 2 5 5 )。
■ 性能与效率问题是什么?有些类型比另外一些类型的处理效率高。数值运算一般比串的运算快。短串比长串运行更快,而且磁盘消耗更小。定长类型比可变长类型的性能更好。
■ 希望对值进行什么样的比较?对于串,其比较可以是区分大小写的,也可以不区分大小写。其选择也会影响排序,因为它是基于比较的。
■ 计划对列进行索引吗?如果计划对列进行索引,那么将会影响您对列类型的选择,因为有的MySQL版本不允许对某些类型进行索引,例如不能对BLOB 和TEXT 类型进行索引。而且有的MySQL版本要求定义索引列为NOT NULL 的,这使您不能使用NULL 值。
现在让我们来 更详细地考虑这些问题。这里要指出的是:在创建表时,希望作出尽可能好的列类型选择,但如果所作的选择其实际并不是最佳的,这也不会带来多大的问题。可用 ALTER TABLE 将原来选择的类型转换为更好的类型。在发现数据所含的值比原设想的大时,可像将SMALLINT 更换成MEDIUMINT 那样简单地对类型进行更换。有时这种更换也可能很复杂,例如将CHAR 类型更换成具有特定值集的ENUM 类型。在MySQL3.23 及以后的版本中,可使用PROCEDURE ANALYSE( ) 来获得表列的信息,诸如最小值和最大值以及推荐的覆盖列中值的取值范围的最佳类型。这有助于确定使用更小的类型,从而改进涉及该表的查询的性能,并减少存 储该表所需的空间量。
2.3.1列中存储何种类型的值
在决定列的类型时,首先应该考虑该列的值类型,因为这对于所选择的类型来说具有最为明显的意义。通常,在数值列中存储数,在串列中存储串,在日期和时间列中存储日期和时间。如果数值有小数部分,那么应该用浮点列类型而不是整数类型,如此等等。有时也存
在例外,不可一概而论。主要是为了有意义地选择类型,应该理解所用数据的特性。如果您打算存储自己的数据,大概对如何存储它们会有自己很好的想法。但是,如果其他人请您为
他们建一个表,决定列类型有时会很困难。这不像处理自己的数据那么容易。应该充分地提问,搞清表实际应该包含何种类型的值。
如果有人告诉您,某列需要记录“降雨量”。那是一个数吗?或者它“主要”是一个数值,即,一般是但不总是编码成一个数吗?例如,在看电视新闻时,气象预 报一般包括降雨量。有时是一个数(如“ 0 . 2 5”英寸的雨量),但是有时是“微量( t r a c e )”降雨,意思是“雨根本就不大”。这对气象预报很合适,但在数据库中怎样存储?有可能需要将“微量”量化为一个数,以便能用数值列类型来记录降雨量,或 许需要使用串,以便可以记录“微量”这个词。或者可以提出某种更为复杂的安排,使用一个数值列和一个串列,如果填充一个列就让另一个列为NULL。很明 显,可能的话,应该避免最后这种选择;最后这种选择使表难于理解,使查询更为困难。我们一般尽量以数值形式存储所有的行,而且只为了显示的需要才对它们进 行转换。例如,如果小于0.01英寸的非零降雨量被视为微量,那么可以如下选择列值:
对于金钱的计算,需要处理元和分部分。这似乎像浮点值,但FLOAT和DOUBLE 容易出现舍入错误,除了只需要大致精确的记录外,这些类型可能不适合。因为人们对自己的钱都是很敏感的,最好是用一种能提供完善的精确性的类型,例如:
■ 将钱表示为DECIMAL(M, 2) 类型,选择M 为适合于所需取值范围的最大宽度。这给出具有两位小数精度的浮点值。DECIMAL 的优点是将值表示为一个串,而且不容易出现舍入错误。不利之处是串运算比内部存储为数的值上的运算效率差。
■ 可在内部用整数类型来表示所有的钱值。其优点是内部用整数来计算,这样会非常快。不利之处是在输入或输出时需要利用乘或除100 对值进行转换。有些数据显然是数值的,但必须决定是使用浮点类型还是使用整数类型。应该搞清楚所用的单位是什么以及需要什么样的精度。整个单元的精度都够 吗?或者需要表示小数的单元吗?这将有助于您在整数列和浮点数列之间进行区分。例如,如果您正表示权重,那么如果记录的值为英磅,可以使用一个整形列。如 果希望记录小数部分,就应该使用浮点列。在有的情况下,甚至会使用多个字段,例如:如果希望根据磅和盎司记录权重,则可以使用多个列。
高度(h e i g h t)是另外一种数值类型,有如下几种表示方法:
■ 诸如“6 英尺2 英寸”可表示为“ 6 - 2”这样一个串。这种形式具有容易察看和理解的优点(当然比“ 74 英寸更好理解”),但是这种值很难用于数学运算,如求和或取平均值。
■ 一个数值字段表示英尺,另一个数值字段表示英寸。这样的表示进行数值运算相对容易,但两个字段比一个字段难于使用。
■ 只用一个表示英寸的数值段。这是数据库最容易处理的方式,但是这种方式意义最不明确。不过要记住,不一定要用与您惯常使用的那种格式来表示值。可以用MySQL的函数将值转换为看上去意义明显的值。因此,最后这种表示方法可能是表示高度的最好方法。