1. 何为Caché?
Caché是一款高性能对象数据库,其在国内外医疗行业及其他特定需求行业有着广泛的应用和前景,本文中将会对该数据库的主要特性进行一个整体浏览。
1.1. 独一无二的架构
Caché的强大来源于其独一无二的架构设计。在核心,Caché数据库引擎提供了整套服务——包括数据存储,并发管理,事务和进程管理——这些都是构建复杂数据库管理系统所必须的。可以将Caché引擎认为一个强大有力的数据库工具包。通过该工具包,Caché实现了一款完整的对象关系数据库管理系统。
该架构的好处是多方面的:
1)对象和关系数据库系统可以非常高效的与数据库引擎直接对话;没有对象关系中间件或SQL到对象的桥梁技术。
2)数据库与其物理实现的逻辑分离,使得应用可以彻底重新配置部署而无需改变应用逻辑。
3)因为数据库引擎接口是开放的,其特性可以在需要时直接使用。这可以从构建自己定制的数据库管理系统,到为性能关键的应用进行有目标的优化。
4)对未来的平台: Caché架构可以做到增强未来数据库引擎而不会影响现有应用。例如:Caché4.1版本引入了全新的物理数据结构,戏剧性的提高了扩展性和性能,其不仅无需改变现有应用,也无需对Caché对象关系系统做出改变。当新技术出现时,Caché可以作为内部、高性能组提供支持,而对现有应用没有影响。
1.2. 可进行关系访问的高性能对象数据库
Caché被设计来超越关系模型限制,同时,为数以千计的关系数据库应用提供演进升级路径,也为市场上的很多基于SQL的报表工具提供支持。
除了其为一款高性能对象数据库,Caché也是一款具备完全特性的关系数据库。其中的所有数据作为真正关系表可用,且可通过ODBC,JDBC或对象方法通过标准SQL进行查询和修改。因为底层强大的Caché数据库引擎,相信Caché是目前可用的最快速,最可靠和最具扩展性的关系数据库。
此外,Caché其特性超越了关系数据库的限制 ,而其还支持数据的标准关系视图。这些特性如下:
1)能够建立对象数据模型(每个具备自动创建且同步的内部关系描述),同时,消除了数据库和面向对象应用环境间的阻抗不匹配,也减少了关系面模型的复杂性。
2)一个简单、基于对象的并发模型。
3)用户定义的数据类型。
4)数据库引擎内能利用方法和继承,包括多态。
5)SQL处理对象个性和关系的对象扩展。
6)单个应用内能混用SQL和基于对象的访问,分别在最合适的场景使用它们。
7)为了确保应用的最大性能,可以控制用于存储数据的物理设计和聚集(Clustering)。
大部分支持对象和关系访问的数据库,只是基于一种提供另一种访问方式,但Caché的SQL和对象方面都是直接访问数据——以便用户可以享受到每种方法的优势。
1.3. 广泛的工具集
Caché提供了广泛的工具集,其中包括:
1)ObjectScript, Caché中使用最多的语言。
2)SQL,MultiValue和Basic的内部实现。
3)开发完善的、内建的安全模型。
4)支持数据库和web应用快速开发的一套技术和工具。
5)内置的,基于对象的XML和web服务支持。
6)设备支持(像文件,TCP/IP,打印机)。
7)通过Java, JDBC, ActiveX, .NET, C++, ODBC, XML, SOAP, Perl, Python等更多自动互通。
8)常用Internet协议支持:POP3, SMTP, MIME, FTP等。
9)最终用户的可重用的用户门户。
10)非结构化数据分析支持。
11)商业只能(BI)支持。
12)内建的测试工具。
1.4. Caché现状
Caché被广泛应用于世界范围内,从单用户嵌入系统到成千上万并发用户的企业范围的多服务器安装,以及州级和国家级的应用。
用Caché构建的小部分应用示例包括:
1)作为大型医疗保健网络的应用平台,运行数百个危重患者相关的应用程序。该网络包括一套作为数据和应用服务器的Caché系统,其拥有超过30000的客户端机器。
2)作为大型金融机构的基于java的企业消息传递系统的数据服务器。选择Caché是因为其性能及其传统关系库不可能实现的执行定制化任务的能力。
3)作为一个基于SQL的OLTP(在线事务处理)系统,用于一个拥有超过1400并发用户的大型政府组织。Caché是一个其他关系产品执行失败时的一个立即可用的替换(无需应用改变)。
4)作为一个用于领先科技大学在线教育系统的对象数据库和web应用框架。选择Caché 因为其快速开发(应用必须在三个月内构建完成),对象能力,及其无需应用重构的扩展能力。
5)作为一款对象数据库,用于跟踪世界锦标赛中职业运动员的实时位置和速度。选择Caché是因为其性能(与领先对象和关系数据库比较)及其内部C++接口。
6)作为一个数百万用户的主web站点的分布式SQL数据引擎。该站点使用一套成本高效的基于Linux的服务器,并使用Caché分布式数据管理提供可扩展的,无中间件或web缓冲的个性化站点。该系统的硬件成本(4台现成的Linux机器)不到“Internet应用的领先数据库”报价的10%。
2. Caché数据库引擎
Caché的核心是Caché数据库引擎。该数据库引擎在性能、并发性、可扩展性和可靠性方面进行了高度优化。有一个高度的平台特定优化,以在每个支持的平台上获得最大的性能。
Caché是一个功能齐全的数据库系统;它包括运行关键任务应用所需的所有特性(包括日志,备份和恢复,以及系统管理工具)。为了帮助降低运营成本,Caché被设计成需要比其他数据库产品少得多的数据库管理。大多数已部署的Caché系统没有数据库管理员。
数据库引擎的主要特性将在下面部分描述。
2.1. 事务性多维存储
Caché中的所有数据都存储于稀疏的多维数组中。与典型OLAP(在线分析处理)产品使用的多维数组不同,Caché在其多维结构中支持事务处理操作(插入、更新、锁定、事务)。另外,与大多数OLAP引擎不同,这些多维结构的大小不受可用内存的限制。相反,Caché包含一个先进、高效的数据缓存。
由于Caché数据本身是变长的,且存储于稀疏数组中,因此Caché通常需要不到关系数据库所需空间的一半。除了减少磁盘需求,紧凑的数据存储还增强了性能,因为通过一个I/O可以读或写更多数据,且可以更有效地缓存数据。
多维数组为应用程序如何存储其数据提供了很大的灵活性。例如,一组密切相关的对象,假如一个Invoice对象及其对应的LineItem对象,可以很容易地进行配置,以便LineItem对象与Invoice对象在物理上进行集群,以实现高效的访问。
与传统关系数据库使用的二维结构相比,事务性多维存储的灵活性使Caché具有显著的优势:正是这种灵活性使Caché能够成为高性能的SQL、对象和XML数据库,而无需折中。这也意味着Caché应用程序为未来的技术变化做好了更好的准备。
2.2. 映射
使用一个称为映射的独一无二的特性,可以指定如何将一个或多个数组(或数组的一部分)中的数据映射到一个物理数据库文件。这种映射是数据库管理任务,且无需更改类/表定义或应用逻辑。此外,映射可以在特定的稀疏数组内完成;可以将一个范围的数值映射到一个物理位置,同时将另一个范围的数值映射到另一个文件,磁盘驱动器,或者甚至映射到另一个数据库服务器。这使重新配置Caché应用程序(像为了扩展)成为可能。
2.3. 进程管理
进程是运行在Caché服务器上的Caché虚拟机的一个实例。典型的Caché服务器可以同时运行数千个进程,具体取决于硬件和操作系统。每个进程都可以直接有效地访问多维存储系统。
Caché虚拟机执行的指令(称为P-code)针对数据库、I/O和事务处理和数据仓库应用通常需要的逻辑操作进行了高度优化。
2.4. 锁管理
为支持并发数据库访问,Caché包含了一个功能强大的锁管理系统。
在拥有数千用户的系统中,减少竞争进程间的冲突对于提供高性能至关重要。最大的冲突发生在希望访问相同数据的事务之间。Caché提供了如下特性来缓解这些冲突:
1)原子操作:为了消除典型的性能热点,Caché支持许多原子操作,即其无需应用级锁。一个例子是其能原子地为对象/行标识分配惟一值(关系应用中的一个常见瓶颈)。
2)逻辑锁:Caché执行更新时并不锁定整个数据页。因为大多数事务需要对少量数据进行频繁访问或更改,Caché支持可按每个对象(行)取出的粒度逻辑锁。
3)分布式锁:分布式数据库配置中(见下一主题),系统自动支持分布式锁。
2.5. 分布式数据管理
Caché最强大的特性之一是其能够将服务器链接在一起,形成分布式数据网络。在该网络中,主要提供数据的机器称为数据服务器,而那些主要承载进程,但很少或没有数据的机器称为应用服务器。
企业缓存协议(ECP)
服务器能用Caché企业缓存协议(ECP)共享数据(以及锁)。ECP之所以有效,是因为数据以包的形式传输。当跨网络请求信息时,应答数据包包括请求数据以及其他相关数据。对象固有的自然数据关系和Caché多维数据模型使得识别和包括最初请求数据相关的信息成为可能。这些“相关的”信息被本地缓存在客户机或应用服务器。通常,后续的数据请求可通过本地缓存满足,从而避免了额外的跨网络访问。如果客户机更改了任何数据,则只将更新传播回数据库服务器。
ECP使应用支持各种运行时配置成为可能,包括多层和点对点。
2.6. 日志管理
为了提供数据库的完整性和可靠性,Caché包含了许多日志记录子系统,用于跟踪物理和逻辑数据库更新。日志管理技术还用于提供事务支持(日志用于执行事务回滚操作)以及数据库跟踪(日志用于将影子服务器与主数据服务器同步)。与系统的其他部分一样,Caché允许您配置其日志系统以满足您的需求。
2.7. 数据库可移植性
Caché运行在多种硬件平台和操作系统上,并为此进行了优化。
用户很容易就可以将使用Caché开发的应用及数据从一个平台移植到另一个平台。这只需在新平台上安装Caché并将数据库文件移动到新系统即可。在某些系统间移动时,可能需要运行一个现有数据转换工具(将一种编码表示转换为另一种)。
2.8. 部署选项
Caché支持各种不同的运行时配置,以部署应用时为用户提供最大的灵活性。用户可以通过更改Caché系统设置来在不同的部署选项之间切换;通常无需更改应用逻辑。
下面列出了一些基本的部署选项。
2.8.1. 基本客户机/服务器配置
在最简单的客户机/服务器配置中,单个Caché数据服务器为多个客户机提供服务(根据应用和平台,可能从一个到数千个)。
客户机/服务器配置
客户端系统可以是以下任何一种:
1)运行通过客户机/服务器协议(如ODBC, ActiveX, JDBC, Java)连接的客户机应用的独立桌面系统。
2)web服务器进程通过Zen、CSP (Caché server Pages)、SOAP或其他连接选项(如ODBC、JDBC)与Caché通信。每个web服务器进程可以为许多基于浏览器或机器对机器的会话提供服务。
3)通过ODBC、JDBC等连接到Caché的中间件进程(如企业Java Bean应用服务器)。 使用多种支持协议之一(包括TELNET和TCP/IP)连接到Caché的设备,如终端或实验室设备。
4)以上的某些组合。.
2.8.2. 影子服务器配置
通过添加一个或多个影子服务器,基于基本的客户机/服务器设置之上构建影子服务器配置。每个影子服务器通过连接和监视它的日志来与主数据服务器中的数据进行同步。
影子服务器配置
影子服务器通常用于服务特别查询、大型报表和批处理进程,以限制它们对主事务系统的影响。它们还可用于提供故障转移系统。
2.8.3. 多层配置
多层配置使用Caché分布式数据库技术—企业缓存协议(ECP)—使更多的客户端连接到系统成为可能。
多层配置
在最简单的多层设置中,一个或多个Caché系统充当应用服务器,置于中央数据服务器和各种客户机系统之间。在这种情况下,应用服务器不存储任何数据,相反,它们托管为客户机执行工作的进程,减少数据服务器的CPU资源消耗。这种类型的配置最适合具有良好“引用局部性”的应用,即大多数事务都涉及合理相关的数据,因此在应用服务器之间的锁定是有限的。这些应用,以及那些具有相当数量的读访问的应用(如大多数典型的web应用),在这个模型中工作得非常好。
也可以进行更复杂的配置,使用多个数据服务器以及存储数据的应用服务器。
通常,应用使用多层配置进行扩展和提供高可用性(应用服务器充当热备份系统)。
3. 对象,SQL和统一数据架构
Caché的一个强大而第一无二的特性是其独特的统一数据架构,该架构提供对存储于Caché中数据的并发、高性能对象和关系访问。
3.1. 统一数据字典
Caché中,用户可以将应用组件建模为对象。对象通过定义对象数据(属性)和行为(方法)的类进行组织。
统一数据架构
每个类的元信息或定义存储于称为Caché类字典的公共存储库中。类字典本身是一个对象数据库,存储在Caché中,可以使用对象访问其内容。类字典通过类编译器定义持久对象所需的存储结构,并将类定义转换为并行的可执行代码集,这些代码集提供对该存储结构的对象和关系访问。通过这种架构,对象和关系代码路径高效且自动相互同步。
类定义可以通过以下几种方式添加到类字典中:
1)使用Studio开发环境进行交互。
2)使用关系DDL。Caché接受标准的SQL DDL语句,并自动创建相应的类和表定义。
3)使用文本XML。Caché支持类定义的外部XML表示。这通常用于源代码管理,部署,自动代码生成以及与其他工具的互操作。
4)使用编程对象。使用Caché的类定义对象集,用户可以创建直接与类字典通信的程序,并在应用运行时创建新类。
5)使用Studio中包含的XML模式向导,其可从大多数XML模式文件创建类定义。
3.2. 灵活存储
Caché对象模型与编程语言不同,除了属性和方法,用户还能指定与存储相关的行为,如索引、约束和存储结构。
持久对象使用的存储结构独立于类的逻辑定义且很灵活:开发人员可以使用类编译器提供的默认结构,也可以针对特定情况对结构进行调整。
3.3. Objects
Caché包含功能齐全的下一代对象数据库,专门为复杂的、面向事务的应用需求而设计。Caché对象模型包含以下特性:
1)类:用户可以定义表示应用组件的状态(数据)和行为(代码)的类。类用于创建对象的实例,作为运行时组件和存储于数据库中的项目。
2)属性:类可以包含属性,其确定与每个对象实例关联的数据。属性可以是简单的文字(如字符串或整数)、用户定义的类型(使用数据类型类定义)、复杂(或嵌入式)对象、集合或对其他对象的引用。
3)关系:类可以定义对象的实例如何相互关联。系统自动为数据库中的关系以及参照完整性提供导航方法。
4)方法:类可以通过方法定义行为:与对象相关联的可执行代码。对象方法在Caché服务器进程中运行(尽管可以从远程客户机调用它们)。对象方法可以使用ObjectScript、SQL编写脚本,也可以使用方法生成器生成,方法生成器是根据用户定义的规则自动创建自定义方法的代码。
5)对象持久化:持久化对象能够自动将自身存储于数据库和检索。持久性支持包括完整的数据库功能,包括自动事务管理、并发控制、索引维护和数据验证。持久化对象通过SQL查询自动可见。
6)继承:通过从现有类派生新类,用户可以重用以前编写的代码,以及创建类的专门版本。
7)多态性:Caché支持完整的对象多态性。这意味着应用可以使用定义良好的接口(由超类提供的一组方法和属性),系统将根据每个对象的类型自动调用正确的接口实现。这使得开发灵活的数据库应用更加容易。
8)Swizzling(也称为“延迟加载”):Caché在从其他对象引用任何相关的持久对象时,自动地swizzling(从磁盘带入内存)。这大大简化了处理复杂数据模型的工作。
Caché对象功能不是Caché的一个独立部分;它是Caché编程的核心部分,与其他地方描述的关系访问完全集成。
3.4. 定义类
Caché中定义类最简单、最常见的方法是使用Studio开发环境。Studio允许用户在语法着色编辑器中使用简单的文本格式或使用图形化的指向-点击界面定义类。这两个视图可互换且自动同步。
下面是一个非常简单的持久对象Component的定义,就像在Studio中看到的那样:
Class MyApp.Component Extends %Persistent
{
Property TheName As %String;
Property TheValue As %Integer;
}
该类被定义为持久化类(也就是说,它可以将自己存储在数据库中)。在本例中,Caché提供的新选项卡(a new tab)类(系统类名以“%”字符开头,以区别于应用程序类)中, % persistentopen通过继承提供了所有所需的持久性代码。类属于包“MyApp”。包将相关的类分组在一起,极大地简化了大型应用的开发。该类定义了两个属性:Thename和TheValue,前者为字符串值,后者为整数值。
从ObjectScript代码内,比如在一个方法内,用户可以使用这个对象的语法操作Component对象的实例:
// 创建一个新的component对象
Set component = ##class(MyApp.Component).%New()
Set component.TheName = "Widget"
Set component.TheValue = 22
// 将该新Component对象存入数据库中
Do component.%Save()
用Basic,用户可以定义一个方法来操作Component对象的实例:
' 创建一个新的Component对象
component = New Component()
component.TheName = "Widget"
component.TheValue = 22
'将该新Component对象存入数据库中
component.%Save()
此时,Component的一个新实例存储于数据库中,其具有系统分配的惟一对象标识符。稍后可以通过打开它(使用它的对象标识符)来获取该对象:
' 打开一个实例并将其值翻倍:
component = OpenId Component(id)
component.TheValue = component.TheValue * 2
component.%Save()
用户可以使用内部Java、C++或其他Caché客户端绑定执行完全相同的操作。类编译器可以生成并同步外部访问对象所需的任何附加代码。例如,如果用户将Caché与Java一起使用,则可以指定类编译器自动生成和维护Java代理类,这些代理类提供对持久数据库类的远程访问。Java程序中,用户可以很自然地使用该对象:
// 从数据库中得到Component的一个实例
component = (MyApp.Component)MyApp.Component._open(database, new Id(id));
// 检查该对象的某些属性
System.out.println("Name: " + component.getTheName());
System.out.println("Value: " + component.getTheValue());
3.5. SQL
Caché SQL是一个功能齐全的关系数据库引擎,其与Caché对象技术完全集成。除了标准的SQL-92特性外,Caché SQL还提供:
1)支持流(在SQL中称为二进制大对象,或BLOBS)。
2)支持存储过程(作为对象方法实现)。
3)一组基于对象的扩展。
4)用户定义的数据类型。
5)支持事务性位图索引。
位图索引,通常用于大型数据仓库和OLAP系统,提供了执行基于复杂条件组合的高速搜索的能力。然而,这种位图索引不能实时更新,通常以批处理的方式更新。Caché SQL支持提供高性能搜索功能的位图索引,同时不会损失插入/更新性能。这使事务处理应用能够执行数据仓库风格的查询,并使数据仓库应用能够执行实时更新。
3.6. 对象/关系连接
Caché字典中的所有组件都定义为类。类编译器自动将持久类投影为关系表。对于每一个对象特性,都有一个对应的关系等价物,如下表所示:
对象特性的关系视图
Object Feature | Relational Equivalent |
Package | Schema |
Class | Table |
Object instance | Row within a table |
Property | Column |
Relationship | Foreign key |
Embedded object | Multiple columns |
Method | Stored procedure |
Index | Index |
当Caché加载SQL DDL(数据定义语言)语句时,它使用与此投影相反的方法来创建与关系表对应的类。
为了说明对象到关系的投影,请考虑一个简单的示例。下面是一个简单的、持久的Person类(称为“MyApp”包的一部分)的定义,它包含两个属性,Name和Home:
Class MyApp.Person Extends %Persistent
{
Property Name As %String(MAXLEN=100);
Property Home As Address;
}
Person类从Caché提供的新选项卡(a new tab)中的% persistentopened超类中获得持久行为。Name属性被定义为一个不超过100个字符的简单字符串。
Home属性说明了复杂的用户定义数据类型的使用,本例中是Address类,其定义为:
Class MyApp.Address Extends %SerialObject
{
Property City As %String;
Property State As %String;
}
Address类派生自新选项卡(a new tab)中的%SerialObjectOpens超类。该类提供了序列化自身(将自身转换为单字符串表示)和将自身嵌入到另一个包含类(如Person类)的能力。
当通过SQL查看时,Person类具有以下结构:
SQL查看的Person类: SELECT * FROM Person
ID | Name | Home_City | Home_State |
1 | Smith,John | Cambridge | MA |
2 | Doe,Jane | Dallas | TX |
注意,对象标识符作为列可见。此外,嵌入式Address对象的字段被投影为单独的字段。这些字段被赋予合成名称Home_City和Home_State,它们的行为就像被定义为两个单独的字段一样。
3.7. 继承和SQL
继承是基于对象的系统中的一个重要特性,而在关系数据库中完全没有。Caché SQL使得用标准关系结构来使用继承的功能成为可能。例如,我们可以从前面例子中使用的Person类派生出一个新的Employee类:
Class MyApp.Employee Extends Person
{
Property Salary As %Integer(MINVAL=0,MAXVAL=100000);
}
新类通过增加了一个另外的属性Salary对Person类进行了扩展。
用SQL查看时,Employee类有下列结构:
SQL查看的Employee类: SELECT * FROM Employee
ID | Name | Home_City | Home_State | Salary |
3 | Divad, Gino | Irvine | CA | 22000 |
注意,所有继承的属性都可以作为列使用。还要注意,这里只包含Employee的实际实例行。如果我们再次请求所有Person实例:
修改SQL查看的Person类: SELECT * FROM Person
ID | Name | Home_City | Home_State |
1 | Smith,John | Cambridge | MA |
2 | Doe,Jane | Dallas | TX |
3 | Divad, Gino | Irvine | CA |
本例中,我们看到所有行都被返回,因为每个Employee都被定义为Person的一个实例。然而,在本例中,只显示Person定义的属性。
3.8. 对SQL的对象扩展
为了更容易地在对象应用中使用SQL, Caché包含了许多对SQL的对象扩展。
这些扩展中最有趣的一个是使用引用(“- > ”)操作符跟踪对象引用的能力。例如,假设有一个Vendor类,它引用另外两个类:Contact和Region。你可以使用引用操作符来引用相关类的属性:
SELECT ID,Name,ContactInfo->Name
FROM Vendor
WHERE Vendor->Region->Name = 'Antarctica'
当然,用户也可以使用SQL JOIN语法表达相同的查询。引用操作符语法的优点是它简明易懂。