InterBase 6.5的新特性
作者:Bill Todd(Team B成员)
译者:TR@SOE
原文URI:http://www.dbginc.com/tech_pprs/IB65New.html
1. 改良的缓存管理
2. 指定处理器
3. 取消语句的执行
4. 元数据的安全性
5. 64位文件I/O
6. ROWS语句
7. 以XML格式导出数据
8. 其它改进
改良的缓存管理
以前版本的IB中,如果缓存大小超过10,000页,性能将会降低。该问题已经得到解决。缓存管理器也进行了修改以减少处理大缓存时的额外开销。例如,65,000页缓存所需要的总内存量几乎减少了七兆。分配大的缓存空间的速度也得到提高,缓存I/O的效率也得到提高。在重负载的情况下,线程需要等待共享页面加锁而带来的问题也消除了。增加缓存大小并不能保证性能的提升,但是绝对没有坏处。在用户数量大和其它一些场合时,增加缓存大小会有帮助。
指定处理器
在运行WINDOWS的多处理器系统中,IB超级服务器版本的性能可能会降低,因为WINDOWS总是不断地将IB进程从一个处理器切换到另一个处理器。WINDOWS版本的IB 6.5可以在IBCONFIG文件中包含如下的指令:CPU_AFFINITY 1从而将IB进程与第一个处理器连接。通过改变数值,你可以将IB与任何一个处理器相连接,方法是修改对应的处理器的位。例如,1代表第一个处理器,2代表第二个,4代表第三个。这一语法允许你将IB分配到多个处理器上(IB 7将支持SMP)。例如,将IB分配到第二和第三个处理器时,可以这么写:CPU_AFFINITY 6。
取消语句的执行
使用IB的API函数isc_dsql_free_statement可以取消任何语句的执行。如下所示:
procedure TfrmMain.StopQuery;
var
StatementHandle: TISC_STMT_HANDLE;
ISC_Result: ISC_STATUS;
begin
StatementHandle := dmMain.ibqTest.StmtHandle;
ISC_Result := isc_dsql_free_statement(StatusVector, @StatementHandle, DSQL_CANCEL);
if ISC_Result > 0 then IBDatabaseError;
end;
在运行语句的线程里不可以取消该语句的执行。因此,如果你希望使用这一特性,应该在一个后台线程中运行你的SQL语句。该API调用不能与dbExpress或BDE合用,因为它们无法存取语句的句柄,而该句柄是函数调用的第二个参数。InterBase Express中提供该属性,上面的代码来源于一个使用IBQuery的应用,它在一个后台线程中执行SQL语句。
你取消一个语句的执行时,IB的表现如同该语句执行时出错。被取消的语句所做的一切更改都被取消,但是事务处理还将继续。你可以决定是要确认还是回滚事务。如果在ISQL中你执行了一个语句而又想取消,只要按Ctrl+C即可。
元数据的安全性
在以前版本的IB中,你可以对系统表格授权或取消授权,但是这些权限在备份与恢复后不被保留。IB 6.5就不同了。你创建的任意数据库中所有系统表格给予公众的缺省权限是SELECT。它允许用户看到系统表格,但是他们不能直接修改系统表格。IB 6.5有三个脚本,让你轻松地修改系统表格的权限。readmeta.sql脚本将系统表格给予SELECT权限。writemeta.sql脚本将系统表格给予所有的权限。而blindmeta.sql脚本收回所有给予的权限。
限制系统表格的存取绝不是限制用户使用DDL语句修改数据库中其它表格的能力。IB引擎做了改进,即使用户没有权限直接操作系统表格,引擎也可以代替用户对系统表格进行相应的修改。
如果你用blindmeta.sql脚本或者在早期的IB中使用REVOKE语句收回了系统表格存取的所有权限,你将根本无法存取数据库。IB 6.5第一次打开IB 6 ODS 10的数据库时,ODS版本将自动升为10.1,而公共用户对系统表格的权限将设置为SELECT。IB 6.5也能打开ODS 9的数据库,但是不会对它们进行任何修改。
IB 6.0可以打开一个ODS 10.1的数据库,只要公共用户对系统表格的权限至少为SELECT以上。不过,如果数据库由IB 6.0服务器备份和恢复,所有对系统表格的存取限制都将丢失。
64位文件
IB现在支持Windows/Linux/Solaris平台上的64位文件I/O操作。数据库的大小将只受限于硬盘的大小。只有2.4核心的Linux提供64位文件I/O。如果是以前版本的Linux,IB 6.5将自动使用32位文件I/O,其表现如IB 6.0一样。
ROWS语句[1]
ROWS语句是IB SQL的扩展,它允许你控制SELECT/UPDATE/DELETE语句所影响的范围。ROWS语句的语法如下:
ROWS <lower_value> [TO <upper_value>] [BY <step_value>] [PERCENT] [WITH TIES]
ROWS语句在SQL语句中的位置如下:
<from_clause>
<where_clause>
<group_by_clause>
<having_clause>
<order_by_clause>
<rows_clause>
要理解ROWS语句到底能做什么的最好方法是看看例子。本文中所有的例子都使用IB自带的Employee数据库。第一个例子中,ROWS语句与ORDER BY连用,选出折扣最高的五个记录:
SELECT * FROM SALES
ORDER BY DISCOUNT DESC
ROWS 1 TO 5
ORDER BY语句将返回的记录以DISCOUNT的降序排列,而ROWS语句将返回的记录数量限制为前五个。尽管你可以独立使用ROWS而没有ORDER BY,但是那样没有什么意义,因为限制返回行的数量就意味着你需要以某种顺序排列的前N个记录。如果你需要返回的第一行就是结果记录集的第一行,你可以把上面的查询简写为:
SELECT * FROM SALES
ORDER BY DISCOUNT DESC
ROWS 5
如果你希望ORDER BY语句中具有相同列值的行都作为前五行显示,你可以使用WITH TIES选项:
SELECT * FROM SALES
ORDER BY DISCOUNT DESC
ROWS 1 TO 5 WITH TIES
该查询将返回8行而不是5行,因为前五行的DISCOUNT字段中的某些数据也出现在其它行中。注意,使用WITH TIES时必须同时使用ORDER BY。
除了固定数量的列,你也可以指定返回结果数据集里一定百分比的行数。如下例所示,它将返回SALES中TOTAL_VALUE在前10%内的记录:
SELECT * FROM SALES
ORDER BY TOTAL_VALUE DESC
ROWS 10 PERCENT
PERCENT选项另一个有趣的应用是选择一个平均分布的行子集。 下面的查询返回五行,每个行与它的邻居在表中的距离都是20%的记录数。尽管该查询没有使用ORDER BY,但是使用ORDER BY也是可以的。例如,要获得根据地理位置均匀分布的行,就可以根据州名或ZIP来排序表格。
SELECT * FROM CUSTOMER
ROWS 100 BY 20 PERCENT
ROWS语句可以和统计值联合使用。下面的查询根据各销售人员的定单总额排序而返回前三个销售人员的信息。第二个查询根据各销售人员的定单总额返回前25%的销售人员信息:
SELECT SALES_REP, SUM(TOTAL_VALUE) AS TOTAL
FROM SALES
GROUP BY SALES_REP
ORDER BY 2 DESC
ROWS 3
SELECT SALES_REP, SUM(TOTAL_VALUE) AS TOTAL
FROM SALES
GROUP BY SALES_REP
ORDER BY 2 DESC
ROWS 25 PERCENT
ROWS语句可以和UPDATE合用,来给工资最高的前10名员工加工资:
UPDATE EMPLOYEE
SET SALARY = SALARY * 1.01
ORDER BY SALARY DESC
ROWS 10
你也可以将ROWS与DELETE合用,来删除工资最高的前10名员工。如果你还想删除那些与前10名员工工资一样的员工,只要加入WITH TIES选项:
DELETE FROM EMPLOYEE
ORDER BY SALARY DESC
ROWS 10
InterBase Express现在包含一个新的类,TIBOutputXML,让你轻松地以XML来读取数据。下表中列出了TIBOutputXML的属性。要使用这个类,你必须在文件中包含IBXML单元。InterBase XML支持是以独立的DLL实现的,所以如果你不需要该功能,也就不用分发该文件。
属性 | 描述 |
HeaderTag | XML流中作为头部标记的字符串。如果它为空,那么就使用"<?xml version="1.0">"作为缺省值。 |
DatabaseTag | 作为数据库标记的字符串。如果为空,就使用"Database"。 |
TableTag | 作为表格标记的字符串。如果为空,就使用"Table"。 |
RowTag | 作为行标记的字符串。如果为空,就使用"Row"。 |
Flags | 有三个成员的属性集。 xmlAttribute:以属性生成XML而不是标记; xmlDisplayNull:在XML数据中包含空值; xmlNoHeader:在XML中不要包含头信息。 |
Stream | 接收XML的流。 |
下面的代码演示了如何导出到XML并将XML显示在DELPHI表单里的一个备注控件里:
procedure TMainForm.ShowXMLBtnClick(Sender: TObject);
var
IBOutputXML: TIBOutputXML;
Stream: TStringStream;
begin
IBOutputXML := TIBOutputXML.Create;
Stream := TStringStream.Create('');
try
IBOutputXML.HeaderTag := '' + #10#13 + '' + #10#13;
IBOutputXML.DatabaseTag := DatabaseEdit.Text;
IBOutputXML.TableTag := TableEdit.Text;
IBOutputXML.RowTag := RowEdit.Text;
IBOutputXML.Stream := Stream;
IBOutputXML.Flags := [];
if AttributesCb.Checked then
IBOutputXML.Flags := IBOutputXML.Flags + [xmlAttribute];
if NullCb.Checked then
IBOutputXML.Flags := IBOutputXML.Flags + [xmlDisplayNull];
if NoHeaderCb.Checked then
IBOutputXML.Flags := IBOutputXML.Flags + [xmlNoHeader];
SelectData;
OutputXML(IBSQL1, IBOutputXML);
Stream.Position := 0;
Memo1.Lines.LoadFromStream(Stream);
finally
IBOutputXML.Free;
Stream.Free;
IBSQL1.Close;
EmployeeTran.Commit;
EmployeeDb.Connected := false;
end;
end;
procedure TMainForm.SelectData;
begin
EmployeeDb.DatabaseName := DatabasePathEdit.Text;
EmployeeDb.Connected := true;
EmployeeTran.StartTransaction;
IBSQL1.SQL.Clear;
IBSQL1.SQL.Add(SQLEdit.Text);
end;
其它改进
InterBase 6.5也包含InterClient 2.5,最新版本的InterBase JDBC驱动(经过升级并与JRE 1.3兼容)。也就是说,要使用InterClient 2.5,你必须安装了Java 2。
以前的InterBase从服务器端向客户端传输VARCHAR字段时,会填充空格以补足字段长度。在慢速或高负载的网络上,这会引起性能方面的问题。这已经得到改进,现在只有VARCHAR字段中实际的内容被传输。
IBConsole也得到了改进,每个数据库包含一个独立的Indexes节点。选择该节点后将显示以表格为分组的所有索引信息:索引名,排序,是否唯一,索引包含的字段,字段的顺序以及该索引是否被激活。如果索引是一个外键约束的一部分,则它所引用的主索引的名称也会得到显示。
结论
虽然到IB 6.5的升级不大,但是它还是提供了很多新的特性。 64位文件I/O将使操作大型数据库更为容易,改进的缓存管理带来了更好的性能。元数据的安全性可以保护你的数据库设计,ROWS语句可以控制DML语句所影响的记录的数量。而导出到XML的功能将使WEB应用开发更为简单。这个升级还是值得的。
[1] 我个人认为这是最重要的改进。——译者注