简介
曾听说过创造性压力吗?它属于那些伪精神哲学之一,它宣称互相作用的力会创造出作为斗争副产品的事物。这有点象小人书里面善与恶之间的斗争。现在,我不想说所有软件工程师都是好人,或者所有硬件工程师都是坏人,但是在他们之间存在着创造性压力。正如 Joseph Campbell 所说的,“不要让您对科学不切实际的憎恶迷惑了您的双眼,以至看不到计算机芯片中的光辉境界。”如果整个表象浪潮一样涌出磁盘并冲入内存,那还能有什么比这更浪漫呢?
有时侯,软件工程师会哀叹硬件发展的步伐太缓慢了:机器磁盘速度太慢、内存组太小并且时钟速度象蜗牛爬行。(当硬件发展赶上的时候,可能我们会忘记 Java™ 应用程序曾经是那么慢。)当新一代硬件出现时,操作系统首先适应,但留给用户的却是,它们只能用 32 位体系架构运行 16 位或(气喘吁吁的)8 位 DOS 应用程序的痛苦。现在压力转到了软件工程师头上:他们什么时候才会重新编译应用程序并利用新硬件所提供的新数据类型和内存可寻址能力呢?在最终的分析中,您将在 8086 上运行的 BASIC 与在 24 路 SMP 上运行的 C++ 进行比较时,运行“Hello World”程序所花费的时间大约与编写该程序所花费的时间一样长。
但是,数据库所要做的远不止是要向显示器输出“Hello World”。与 Web服务器软件期望更高速线路一样,数据库软件期望从磁盘速度、容量、可寻址内存的每次升级中尽可能获得好处。尽管应用程序程序员可能会抱怨必须为 32 位机器重新编译 16 位程序(它已经运行良好了),但是数据库工程师喜欢这样的想法:在将数据排序、聚集或发送给用户之前把它保存在内存中而不是磁盘上。I/O 是如此众多要求过高工作负载的杀手 — 这正是您将 1 TB 的数据分散到 5 TB 的磁盘上的原因(更多的磁盘 = 更多的轴,这意味着更多并行的 I/O,至少在基准测试世界中是这样)。
现在,在 RISC 和 Sparc 世界中,64 位体系架构正逐步成为标准,它允许商业性 UNIX®(如 AIX®、HP-UX 和 Solaris 等)为您喜爱的关系数据库提供大量内存。32 位内存的可寻址能力大约等于 4 GB,而许多 UNIX 机器装有 20 到 100 GB 内存,您肯定希望使用这样大的内存。Intel 世界也不落后多少:现在,操作系统、编译器和数据库软件实验室里,正在 64 位 Intel 芯片上运行的 Linux 和 Windows 2000 是一个现实,而且不久会在您周围的网站上销售。
那么,如果硬件和操作系统都已经为使用巨大的内存做好了准备,并且数据库也能够利用大内存,那么您如何将它们结合起来并使之工作呢?使用 DB2® 版本 7,首先要弄清楚的是,在内部,DB2 假设使用 32 位内存和硬件。要利用更大的内存,必须告诉 DB2 可以使用它以及如何使用它。请勿责备 DB2 — 大多数 DB2 客户机和许多 DB2服务器在未来数年中将运行在 32 位 Intel 机器上。并且即使 DB2 在您机器上检测到有 96 GB 内存,谁又能肯定您希望 DB2 使用所有内存,而不是与其它应用程序共享这个内存呢?
当使用这种大内存时,您有几种选择。最显而易见的选择是创建 64 位 DB2 实例。现在,AIX、Solaris 和 HP-UX 上的 DB2 版本 7 都支持这种操作。如果您拥有版本 7.1,则必须下载修订包 1 以安装 64 位 DB2 库。如果您拥有版本 7.2 或更新版本,则不必为了创建 64 位 DB2 实例而安装修订包。要创建 64 位 DB2 实例,可以使用 DB2icrt 命令,并指定参数 -w 的值为 64。例如:
DB2icrt -w 64 -u DB2fenc1 DB2inst1 |
描述 64 位环境中 DB2 使用的手册位于:
1 + 1 = 2。2 的 32 次方 = 极大的数。
每个 32 位 DB2 实例能够对 4 GB 内存寻址。通常,您希望将大部分内存给缓冲池专用。但是,AIX、HP-UX 和 Windows 上的内存分段会将最大缓冲池的大小限制在 4 GB 以内。即使是在 32 位世界中拥有十分干净的内存模型的 Solaris 上,用于 DB2 缓冲池的内存也不能超过 3.35 GB;4 GB 内存空间的其余内存必须专用于 DB2 的其它共享内存用途。(幸运的是,对于 64 位世界中的所有操作系统,内存模型都更干净。)在 HP-UX 上,32 位 DB2 实例所能够创建的最大缓冲池大约是 800 MB。在 HP-UX 上,只有通过使用 32 位 HP-UX 上的 Memory Windows 来运行多个实例,才能使用 1 GB 以上的缓冲池。(DB2 发行说明(Release Notes)中描述了 HP Memory Windows。)在 Windows 上,缓冲池被限制为 3 GB,AIX 上是 1.75 GB,而 Linux 上大约是 1 GB。
在运行 32 位 DB2 的大内存系统上,要将大量内存给予缓冲池,最简单方式就是在一个 DB2 企业扩展版(Enterprise-Extended Edition (EEE))配置中运行多个逻辑 DB2 实例。只需要运行操作系统的一个实例,这将有助于节省开销和允许多个 DB2 实例之间通过共享内存而不是通过 TCP/IP 或通信交换机来彼此通信。使用 DB2 的无共享体系结构,每个实例可以在它自己的数据库分区之内愉快地对 4 GB 内存寻址。在大多数 DB2 TPC-H 基准测试中 — 它通常让 DB2 EEE 在规模达 300 GB 或更大的数据库上运行决策支持查询 — 一个大型 SMP 为每个 DB2 节点划分多至 4 GB 内存(每个节点都是一个运行它自己的 DB2 实例的数据库分区)。
DB2 还可以使用其它三种方法来利用大内存机器。在 AIX、Solaris 和 Windows 上,DB2 支持扩充存储器(Extended Storage)(也称为 ESTORE)。这允许 DB2 将超过 32 位内存模型中最大可用内存的内存用于系统临时表(用于排序)和只读用户数据。在 DB2 从磁盘获取数据时就由 DB2 判断哪些数据是可以认为是只读,但是需要配置 DB2 以使用扩充存储器。
让我们考虑一种典型情况:您正在设计一个数据库,在其中希望将一个表尽可能多地放入内存。首先,更新数据库管理器配置并告诉它要使用多少扩充存储段(num_estore_segs)。这个值的缺省设置为零。n 取多大值将取决于表有多大、可用的内存有多少以及您希望这个特定表用多少内存。假定我们正在使用 Solaris,它有 6 GB 内存 — 在 4 GB 内存空间之上的 2GB 内存用于扩充存储器(也称为 estore):
update db cfg for sample using num_estore_segs n |
用“扩充存储器存储段大小”(estore_seg_sz)数据库配置参数来定义 estore 段的大小:
update db cfg for sample using estore_seg_sz 32000 |
现在您创建了一个缓冲池。对于本示例,我们将使用 8K 页面大小,尽管 16K 和 32K 页面大小也是允许的。(如果是在 Windows 上,要使用 2GB 以上的内存,则必须使用大于 4K 的页面大小。)必须为扩充存储器启用缓冲池,可以使用 EXTENDED STORAGE 关键字做到。 highmem 是我为这个缓冲池选择的名称。其大小 n 取决于您希望这个缓冲池占用的内存数量:
CREATE BUFFERPOOL highmem SIZE n |
现在创建一个表空间,并将它分配到这个缓冲池:
CREATE TABLESPACE highmem_tbsp PAGESIZE 8K |
注:表空间的页面大小必须与该缓冲池的页面大小相匹配,并且该缓冲池由名称来标识。如果您只在这个表空间中创建一个表,而这个表空间又是该缓冲池中唯一的表空间,那么当访问这个表中的数据时,就增大了数据留在内存中的机会。但对表进行排序时仍可能会溢出,因此请确保有一个已创建了相匹配的页面大小的系统临时表空间:
CREATE SYSTEM TEMPORARY TABLESPACE highmem_temp PAGESIZE 8K |
现在准备在该表空间中创建表:
create table memory_hog (col1 int) in highmem_tbsp |
部分还是全部 AWE?由您来判断。
Windows 2000 能够通过 Microsoft Address Windowing Extensions(AWE)在 32 位世界中映射越过 4 GB 内存界线的数据。DB2 版本 7.2(或带有修订包 3 的版本 7.1)支持这个特性。Windows 2000 Advanced Server 最多支持 8 GB 内存,而 Windows 2000 Data Center Server 最多支持 64 GB 内存。
在最终的分析中,您可能需要做一个选择,这个选择与高性能数据库设计所需的颗粒度是背道而驰的。可以假定,您将考虑的用于上述技术的数据库需要最佳性能 — 最终,如果性能不重要,为什么要将数据库放到拥有大量内存的机器上?此类数据库倾向于将用户数据存储在数据库管理存储器(Database Managed Storage (DMS))中,将原始设备(raw device)用作容器。按照大多数人的意见:如果您管理一个具有众多概要文件和用户要求很高的数据库,那么,需要投入大量时间对数据库进行调整和计划,这样才能预测数据的增长并在原始设备容器上分配足够的空间。用这种思想,可以知道系统管理存储器(SMS)表空间只适于系统数据(临时表空间和目录表空间)和必须对其进行少量维护的数据库,因为,这两者数量太多,因而无法保证对其设计和维护进行大量投资。
假定您同时面临两种最糟糕的情况:一方面数据库必须迅速,另一方面您又无法预测其中的数据增长或去花费大量时间对其进行维护,那怎么办呢?您可能会问:如果有些事情很重要,为什么不将 DBA 资源用于它呢?但老板并不总是理性的。幸运的是,关系数据库架构设计师们并不是仅有的花费大量时间决定如何使用大内存机器的人:操作系统专家也在研究这个问题。您将需要做一个信念上的飞跃,将所有数据放置到 SMS 表空间,并将文件系统用作容器。(也可以使用 DMS 来做这件事,但是在为容器定义文件大小时,还必须计划数据增长)。现在,查看所有 4 GB 内存地址以上的空间并将它用于文件系统高速缓存,是操作系统的任务。幸运的是,由于大多数数据库运行在大型 SMP 上,并且能够通过利用应用程序来达到其性能目标,这推动了系统设计师们挖掘出大内存机器的潜能,以将频繁访问的数据保存在内存中。而这正是人们希望数据库缓冲池所做的:将经常访问的数据保存在内存中,而其余的仅留在磁盘上。
别在家里尝试这个操作!(在工作中、在老板的系统上尝试。)
也许在结束关于内存的文章之前,有必要提醒您不要忘记系统里的其余部分。毕竟,如果您有 96 GB 内存,而磁盘上就可能有不止 96 GB 的数据 — 正等着吞没您的系统并将它送入页面调度的痛苦状态。本文的重点是尽可能多地使用内存。毕竟,您为它花了钱,那么为什么不使用它并使之物有所值呢?按照这种思想,不要忘记您购买的其余硬件。您希望软件使用所有的内存,但也希望所有处理器做它们的那部分工作 — 对所有的磁盘也是如此。正如在 1 MB PC 上将应用程序限制到 640 K 内存不能充分利用可用资源一样(因此比它应有的速度要慢),如果您的一个处理器以 100% 运行,而其它以 25% 运行,这时,您的处境就很尴尬了 — 一个处理器的工作负载已达到了极限,而其余处理器什么也不做。(这种情景就好象您在建筑工地上看到一个人正在拿铁锹工作,而他的同事却袖手旁观。)这正是 DB2 EEE 可以帮助您的地方;它的无共享体系结构被设计成简洁地将所有工作和数据公平地划分给可以使用的内存、CPU 和磁盘。出于这个原因,对于决策支持无共享体系结构是很理想的。对于那些事务型工作负载,您必须监视热点:如果发生了 CPU 或磁盘中的一个子集工作过重的现象,为什么会发生这种现象呢?是因为所有任务繁重的客户机都连接到同一节点了吗?幸运的是,EEE 允许您将客户机连接分布到所有节点。是否应该将数据移到这些节点上的许多小表中,这样在进行更新操作时,就避免了对分布在所有节点的一个大表进行操作的情况。小表的缺点在于:当您希望得到一个需要来自每个节点上行的结果集时,必须进行 UNION 操作。还有,不要怕在无共享体系结构上运行 OLTP。在撰写本文时(2001 年 4 月),TPC-C 测试结果表明:前六名都是集群的无共享数据库。
工作负载平衡还意味着将表空间分布到多个磁盘,这样多个磁盘可以同时返回数据,因而也就启用了并行 I/O。这里,在三个变量之间存在创造性压力:磁盘、内存和处理器。运气好的话,您的每种资源都充足,并且可以在它们之间进行工作负载平衡来构建一个系统,对于您所花费的时间和投资的金钱,这个系统是物有所值的。至于还没有使用的硬件呢?唔,至少它使硬件销售代表挣得大笔佣金可以到夏威夷度假。而且,如果没有其它原因,那么您是否曾发现自己在夏威夷钓鱼而您的小艇和海浪搏斗时,这些额外的硬件和一根绳索就会形成一个可靠的锚。
关于作者