在逻辑设计向物理设计转化的过程中,必须做出四个决定。第一,对于每个表,不仅需要决定是否使用堆表、聚簇或索引组织表,也需要决定是否对这个表进行分区。第二、需要考虑是否采用冗余的访问结构,比如索引组织表。第三、需要决定如何实现数据约束(而不是是否实现它)。第四、必须决定如何将数据保存在数据块中,还包含字段的顺序,使用何种数据类型,每个数据块可以保存多少条记录,以及是否激活数据块上的压缩。
最佳字段顺序
最佳字段顺序:
很少有人关心如何寻找一个表的最佳字段顺序。根据环境不同,可能一点影响也没有,也可能产生很大的开销。为了理解在哪些情形下可能带来很大的开销,必须先理解数据库引擎是如何将数据保存到数据块中的。
保存到数据块中的记录有个非常简单的结构。首先,会有一个头(H)记录这条记录的一些基本属性,诸如是否被锁住或者包含多少个字段。其次,就是它的字段。由于每个字段可能有不同的大小,所以每个字段包含两个部份。前一部份是数据长度(Ln),后一部份是数据本身(Dn)。
存储在数据库库块中每一行记录的格式(H=行头,Ln=字段n的长度,Dn=字段n的数据)
理解这个格式的关键是,数据库引擎不知道一条记录中每个字段的偏移量(offset).例如,如果需要定位字段3,必须从字段1开始。接着根据字段1的长度来定位字段2.最后,根据字段2的长度来定位字段3.因此,无论何时一条含有多个字段的记录,靠近记录开始的地方的字段定位的速度会明显快于靠近记录未尾的字段。为了更好的理解这一点,你可以运行脚本column_order.sql来进行测试,以估算搜索一个字段的额外开销。
select count(city) from tmp_mms;
select count(xiaoqu) from tmp_mms;
注:通过这个可以测试出来,第一个字段的速度明显快于最后一个字段的查询速度。在数据量的情况下,非常的明显,你可以去测试
由于这个原因,一般的规则是将访问频繁的字段放在前面。为了利用这一点,需要仔细确认只有访问(引用)真正需要的字段。无论如何,从性能的角度看,查询不需要的字段(或者更甚,使用select * 引用所有字段,即便事实上只有几个字段被应用程序使用,很遗憾,这种事情经常发生)都是不好的,不仅是因为当从数据块中读出时会额外开销,而且是因为在服务器端和客户端都需要分配更多的内存来临时保存这些数据,以及需要更多的时间和资源来通过网络传输这些数据,简单来讲,就是只要数据被处理,就会带来开销。
实际操作中,与字段顺序相关的额外开销在下面几种情况中(更加)显而易见。
n 当一张表包含大量的字段,并且SQL语句经常访问记录后面的很少几个字段
n 当从同一个数据块中读取很多记录时,比如在做全表扫描的时候。这是因为,定位并访问一个数据块的开销要比定位并访问字段(只读取几条记录)时的开销多得多。
由于未尾的NULL值是不保存的,所以将可能包含NULL值的字段放在表的未端是合适的。这样,实际存储的物理字段数量以及相应的行的平均大小也可能降低。