用户登录  |  用户注册
首 页商业源码原创产品编程论坛
当前位置:PB创新网文章中心编程技巧计算机应用

分布式网络系统中的数据访问设计与优化

减小字体 增大字体 作者:佚名  来源:本站整理  发布时间:2009-01-10 11:49:44
【本文由PB创新网为您整理】

  要: 在基于局域网的大型分布式仿真和控制系统中,包括数据库服务器在内的各计算机之间的信息交互方案的设计是系统性能优异的关键,尤其是在计算机数量较多或待交互的单位时间信息量较大时更为重要。计算机间的信息交互涉及各机间的共享数据的读取、存贮和更新等方面的内容,需采取有效的系统规划、实时通讯和快速数据库访问等手段解决。本文全面论述了有关内容,给出了有效的解决方案。

关键词:网络系统、 信息交互、优化设计

1  前言

随着计算机和网络技术的不断提高,使用基于局域网的,分布式的计算机系统对大型、综合或复杂的工业过程和运行环境进行系统仿真与运行模拟以及控制已越来越普遍。由于这样的仿真与控制系统一般规模庞大或过程复杂,单独一台计算机无法完成整个系统任务,需要多机参与,构成计算机网络,通过网上信息交互共同协调完成整个仿真与控制任务。各机之间信息交互的方式、频率和数量决定了整个网络系统的综合性能。由于在这样的系统中,机间的信息交互一般都非常频繁,各机都要面临数据更新、系统运行、结果存贮等过程的快速性问题,因此有关的设计是非常重要和关键的。

2  系统规划与设计

无论是仿真还是控制系统,合理的系统和数据规划至关重要。通过系统和数据规划可以优化系统设计,解决各机任务均衡,资源充分利用等问题,在兼顾可靠性、安全性和故障可诊断性的同时充分发挥系统的整体效率和性能,并容许具有一定的可扩展性。

目前有许多分布式仿真和控制系统采用以数据库为中心的设计方案。在这种设计方案中,网上的交互信息通过数据库来进行,首先由产生交互信息的机器存入数据库,然后由需要该交互信息的机器从数据库中读出来完成一个信息交互或更新过程。由于该信息交互通过一个中间环节即数据库来进行,因此在网上的计算机数量较多或程序要求的数据更新较多较快时,易造成数据冲突和网络堵塞,极易导致系统运行迟缓或死机,成为整个系统性能的瓶颈。

当然以数据库为中心的分布式仿真和控制系统也有其优点,其编程思路比较简单清晰,容易被人理解和掌握。对于网上信息交互量不多的系统,可以采用以数据库为中心的系统,同时可以通过数据规划合理地分配各计算机的任务,使用一些编程技术来降低网上的信息流量,提高系统的性能。例如在程序中应尽量使用全局变量创建公用数据库连接,避免每次不必要的数据连接重建时间。

如果系统较大、网上信息交互量较多或对系统实时性和可扩展性要求较高时,应采用实时网络数据通讯的设计方案。在以数据库为中心的系统设计方案中,由于数据的变化首先要存入数据库,然后被其它程序访问才能刷新,经历了数据库存取这一中间环节。如果网上有多个应用程序都需要知道该数据的变化,则都必须通过数据库访问才能更新。这样就浪费了许多网络资源,容量造成瓶颈。在采用实时网络数据通讯的设计方案中,通过网络实时通讯来解决网上各机器间的数据交互与刷新问题,其中对于多台机器都需要的数据变化通过网络广播的方式,以定时和数据变化实时触发传送的机制向所需机器通知该数据已发生变化和具体的数值;对于只存在两台机器之间的信息交互可采用点对点的方式进行通讯。通讯的数据格式和组织可以自行定义。因此,与以数据库为中心的方案相比,该设计方案减少了因数据刷新所需的多次访问问题,大大减少了数据流量,同时网络传输还可以增加数据正确性和合法性校验,为操作者或系统管理员及时提供系统信息和出错信息,便于系统故障诊断和系统调试。

如果把各子系统初始化数据都保存在服务器的数据库中,则各机一起启动时,由于都需要建立数据库链接,读取其中的初始化数据,容易造成起动时间过长的现象。为此,对于不必要存于服务器的数据可存于本地数据库中,本地数据库可采用ACCESS数据库。对于一般不变的系统初始化数据也可以备存到本地数据库中,供日常程序起动时使用。如果系统的初始化数据进行了更新,可以编制一段程序,根据数据库服务器的数据库版本号来更新本地数据库。无论何种方案,数据库的访问总是不能避免的,如何提高数据库的访问速度非常值得研究。

3  提高数据库访问速度(SQL数据库为例)

客户机程序一般采用VC++VBPowerBuilderDelphi等支持访问数据库的集成开发环境进行开发。在编写客户端程序时,一般通过ODBC(Open Database Connectibvity) APIRDO(Remote Data Objects) [5]ADO(ActiveX Data Objects) [5]访问数据库,查询或修改数据库中的数据。其中ODBC API是被人们广泛接受的用于数据库访问的应用程序编程接口。具有访问数据库速度快效率高,但编程复杂的特点;远程数据对象(RDO)ODBC API函数进行了封装,为编程人员提供了一个访问远程数据库的高级接口,在程序中通过该对象可轻松对数据库进行远程访问。组件对象(ADO)不仅继承而且发展了RDO,它不但具有访问远程数据库的能力,而且还具有访问其它数据提供者(不一定是数据库,可能是其他文件或其他应用程序所提供的数据)的能力。在VB中可很方便的使用RDOADO来访问数据库,但访问数据库效率不高,速度较慢,灵活性也差。为了满足系统的要求经常需要提高访问数据库的速度,具体方法有:

3.1  使用ODBC API函数

由于ODBC API函数的入口参数表中有些参数需要传递指针,而VB不支持指针,因此在VB中调用ODBC API函数会有一定的限制。另外,VB的字符串内存存储格式与C语言不同,而ODBC API函数是用C语言开发的,这也限制了VBODBC API函数之间的数据交换。为此需要开发一个动态链接库(Dynamic Link Library - DLL),编制二个API函数分别以获取参数指针和支持数据交换,从而实现在该动态链接库的支持下,在VB中直接调用ODBC API函数的目的。

可以使用VC++6.0开发动态链接库。VC++6.0可开发三种类型的动态链接库:Win32 DLL、常规 MFC DLL、扩展 MFC DLL。其中Win32 DLL、常规 MFC DLL可被任意Win32编程环境(包括Visual Basic 6.0)加载使用。常规 MFC DLL在发行时必须附带MFC42.DLL库,而Win32 DLL可单独发行[3]。如果只提供给VB编程环境使用,可建立Win32 DLL即可。

具体的开发步骤为:利用VC++6.0编程环境的AppWizard创建一个简单Win32 DLL工程,工程名为SQLAPI,在此基础上加入自己的代码。代码如下:

#include "stdafx.h"

#define DLLEXPORT  extern "C" __declspec( dllexport) //定义导出宏

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)

{  return TRUE;         }

DLLEXPORT long __stdcall GetAddress(void * Address) //按地址传送

{  return (long) Address;       }//将地址强制转换为长整形

DLLEXPORT long __stdcall strCopyToByte (char * BytesAddress,char * strAddress)

{  return (long) strcpy(BytesAddress, strAddress); }//将字符串传送到指定地址

经编译链接生成SQLAPI.DLL动态链接库,将其拷贝到C:/WINDOWS/SYSTEM(对于Windows C:/WINNT/SYSTEM32(对于Windows NT 2000)目录下,这样就可在VB中调用这两个API函数实现对ODBC API的调用。ODBC调用的一般流程为:

1连接至数据源:分配环境句柄、设置环境属性、分配联接句柄、联接数据源和设置联接属性。

2初始化应用程序:分配语句句柄、设置语句属性,必要时进行数据绑定。

3建立和执行SQL语句:a) 建立SQL语句,或使用硬编码的SQL语句。b) 如果SQL语句含有参数,将每个参数绑定至应用程序变量。c) SQLExecDirect执行该语句。如果语句要多次执行,则进行语句准备,并用SQLExecute来执行。

使用API函数可以加快数据库的访问,提高效率,另外也要注意SQL语句的语法优化。对于巨表和多表访问,SQL语句的语法优化对访问速度的影响会显得尤为重要。

3.2  SQL优化

应从数据库端和客户端程序两方面入手,提高访问SQL数据库的速度,提高查询和修改数据库数据的效率。在数据库的表中记录数很多时,访问速度尤其重要,由于SQL数据库采用先进的索引技术和高效的查询算法,因此在保证结果正确的同时,要注意选用性能最佳的实现方法。其中可以通过对数据库的索引,多表间的连接和where子句进行适当的优化,使运行速度大大提高,同时可使用存储过程来使SQL变得更加灵活和高效。

SQL数据库可高效处理成批和成组的数据,而对于单个数据处理则效率低下,因此,在编写客户端程序时,应尽量将数据成批(成组)地送往数据库,或成批(成组)地查询数据。另外,在客户端,使用SQL语句也存在优化问题。如:

dim mValue as Single, strSQL as string

mValue=12.34

strSQL=”UPDATE tablename SET value = “+str(mValue)+” WHERE name=’Generator’”

SQLExecDirect(语句句柄, strSQL ,SQL_NTS);

该语句将表tablenamename=’ Generator’记录的value值更新为12.34,该操作在程序运行中经过两次转换,首先将单精度数转换为字符串,和其他字符串合并后传递给ODBC 驱动程序,驱动程序又将字符串再转换为ODBC特有的数据格式,如更新大量数据则花费在转换数据格式上的系统开销很大,应尽量避免编写上述代码。对于多次常用语句应进行语句准备,以后可多次使用。

一般来说,针对有大量重复值、且经常有范围查询(between, >,< >=,< =)和order bygroup by发生的列,建立非缺省的群集索引可能会使性能更佳,而对于经常同时存取多列,且每列都含有重复值的情况可考虑建立组合索引,注意组合索引要尽量使关键查询形成索引覆盖,其前导列一定要是使用最频繁的列。

在进行多表操作时,可在执行前根据连接条件,使用查询优化器列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充分考虑带有索引的表、行数多的表。内外表的选择可由下列公式确定。其中乘积最小的方案为最佳。

乘积=外层表中的匹配行数*内层表中每一次查找的次数

where子句中,任何对列的操作都将导致表扫描,这些操作包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。假设有如下两个SQL语句,其条件语句中的列value已建有恰当的索引

语句1select * from Table1 where value/30<100

语句2select * from Table1 where value<100*30

在表中数据很多时,可明显看出语句2的运行速度比语句1快得多,这是因为where子句中对列的任何操作结果都是在SQL运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用已建在该列上的索引。如果在查询编译时就能得到这些列的操作结果,那么就可以被SQL优化器优化,从而使用索引,避免表搜索,如语句2所示。

where条件中inor子句常会使用临时数据库的工作表,使索引失效;如果子句拆开后不产生大量重复值,可以考虑把子句拆开来优化运行,拆开的子句中应该包含索引。例如,假设在表Parts中有200000行记录,在类型字段Type上有非群集索引,则针对SQL语句:select count(amount) from Parts where Type in('0','1'),因为其where条件中的'in'在逻辑上相当于'or',所以语法分析器会将in ('0','1')转化为Type ='0' or Type ='1'来执行。我们原来期望它会根据每个or子句分别查找,再将结果相加,从而可以利用Type字段上的索引;但实际上它却采用了"OR策略",即先取出满足每个or子句的行,存入临时数据库的工作表中,再建立唯一索引以去掉重复行,最后从这个临时表中计算结果。因此,实际过程没有利用Type字段上的索引,并且完成时间还要受tempdb数据库性能的影响。

SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语句,尽量减少类型转换和计算,充分利用索引,减少表扫描的I/O次数,尽量避免表搜索的发生。其实SQL的性能优化是一个复杂的过程,上述内容只是在应用层次的一些体现,深入研究还会涉及其它内容如数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计等。

4  一个机器只用一个数据备存进程

在分布式的仿真与控制系统中,在同一个机器上经常运行多个进程,这些进程可能都需要进行数据保存工作。为了减少数据链接,减少网络流量,同时增加系统的可靠性和运行的独立性,可采用一个单独的公用数据备存进程来承担其它进程的数据保存功能。其它进程指向数据库服务器的保存操作都通过该模块进行。数据备存进程与其它应用程序进程之间的通讯可通过使用WM_COPYDATA消息进行传输,并使用SendMessage函数解决Windows在通过WM_COPYDATA消息传递期间不提供继承同步方式的问题。在接受方完成数据拷贝前该函数不返回,这样发送方就不可能删除和修改数据。该函数的语法为SendMessage(hwnd,WM_COPYDATA,wParam,lParam),其中wParam为包含数据的窗口的句柄。lParam指向一个COPYDATASTRUCT的结构。

下面给出了应用程序进程向数据备存进程传递数据的具体函数。该函数共有两个参数,第一个参数AppNo标识所在应用程序的序号,第二个参数为要传递到数据备存进程中的具体SQL语句。

void SendRequestToDBServer(long AppNo,const char strSQL[])

{

static char                Data[1024];

COPYDATASTRUCT

Tags:

作者:佚名

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
PB创新网ourmis.com】Copyright © 2000-2009 . All Rights Reserved .
页面执行时间:34,703.13000 毫秒
Email:ourmis@126.com QQ:2322888 蜀ICP备05006790号