本论文在其他论文栏目,由论文格式网整理,转载请注明来源www.lwgsw.com,更多论文,请点论文格式范文查看
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);
该语句将表tablename中name=’ Generator’记录的value值更新为12.34,该操作在程序运行中经过两次转换,首先将单精度数转换为字符串,和其他字符串合并后传递给ODBC 驱动程序,驱动程序又将字符串再转换为ODBC特有的数据格式,如更新大量数据则花费在转换数据格式上的系统开销很大,应尽量避免编写上述代码。对于多次常用语句应进行语句准备,以后可多次使用。
一般来说,针对有大量重复值、且经常有范围查询(between, >,< ,>=,< =)和order by、group by发生的列,建立非缺省的群集索引可能会使性能更佳,而对于经常同时存取多列,且每列都含有重复值的情况可考虑建立组合索引,注意组合索引要尽量使关键查询形成索引覆盖,其前导列一定要是使用最频繁的列。
在进行多表操作时,可在执行前根据连接条件,使用查询优化器列出几组可能的连接方案并从中找出系统开销最小的最佳方案。连接条件要充分考虑带有索引的表、行数多的表。内外表的选择可由下列公式确定。其中乘积最小的方案为最佳。
乘积=外层表中的匹配行数*内层表中每一次查找的次数
在where子句中,任何对列的操作都将导致表扫描,这些操作包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。假设有如下两个SQL语句,其条件语句中的列value已建有恰当的索引
语句1:select * from Table1 where value/30<100
语句2:select * from Table1 where value<100*30
在表中数据很多时,可明显看出语句2的运行速度比语句1快得多,这是因为where子句中对列的任何操作结果都是在SQL运行时逐列计算得到的,因此它不得不进行表搜索,而没有使用已建在该列上的索引。如果在查询编译时就能得到这些列的操作结果,那么就可以被SQL优化器优化,从而使用索引,避免表搜索,如语句2所示。
在where条件中in、or子句常会使用临时数据库的工作表,使索引失效;如果子句拆开后不产生大量重复值,可以考虑把子句拆开来优化运行,拆开的子句中应该包含索引。例如,假设在表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