应用题 某采购中心采购了一套商品批发查询管理系统,此系统采用SQL Server 2008数据库管理系统,该系统需要经常处理百万级以上的数据查询。同时该系统提供了第三方人员开发的SQL接口,第三方人员可以根据自己的需要开发自己的应用程序来访问数据库中的相关数据。
问答题     系统在使用的过程中,业务人员反应系统操作速度很慢。经过工程师检查测试后,数据库系统本身及网络传输过程中存在着一些问题,请给出针对数据库系统本身及网络传输过程中可能的一些调优方案。
 
【正确答案】①把数据、日志、索引放到不同的I/O设备上,增加读取速度,数据量(尺寸)越大,提高I/O越重要。 ②纵向、横向分割表,减少表的尺寸。 ③升级硬件,扩大服务器的内存,Windows 2000和SQL Server 2000能支持4-8G的内存。配置虚拟内存,虚拟内存大小应基于计算机上并发运行的服务进行配置。增加服务器 CPU个数。 ④分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成数据库服务器联合体的机制能够扩大一组服务器,以支持大型的多层Web站点的处理需要。 ⑤重建索引:DBCC REINDEX, DBCC INDEXDEFRAG;收缩数据和日志:DBCC SHRINKDB, DBCC SHRINKFILE。设置自动收缩日志,对于大的数据库不要设置数据库自动增长,它会降低服务器的性能。 ⑥优化锁结构。
【答案解析】
问答题     工程师在完成数据库系统本身和网络问题的优化后,发现第三方开发人员的SQL查询语句存在很多没有优化的问题,请从第三方开发人员角度给出一些优化方案。
 
【正确答案】①对查询进行优化,尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。 ②应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。 ③任何地方都不要使用 select * from 进行全表扫描 ,用具体的字段列代替“*”,不要返回冗余字段。 ④避免频繁创建和删除临时表,以减少系统表资源的消耗。 ⑤尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。 ⑥尽量避免大事务操作,提高系统并发能力。
【答案解析】从数据库本身和网络传输的角度出发,数据库性能低下的因素一般有:I/O吞吐量小,形成了瓶颈效应;没有创建计算列导致查询不优化;SQL Server数据库内存不足;网络速度慢;查询出的数据量过大(可以采用多次查询或其他的方法降低数据量)以及锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)。 从SQL查询语句角度来考虑优化响应时间,应该从查询条件、临时表、游标、返回数据量、大事务操作等方面进行调优。
问答题   已知在文件in.dat中存有100个产品销售记录,每个产品销售记录由产品代码dm(字符型4位),产品名称mc(字符型10位),单价dj(整型),数量sl(整型),金额ie(长整型)五部分组成。其中:金额=单价+数量。函数ReadDat()读取这100个销售记录并存入结构数组sell中。请编制函数SortDat(),其功能要求:按产品名称从小到大进行排列,若产品名称相同,则按金额从小到大进行排列,最终排列结果仍存入结构数组sell中。最后main()函数调用函数WriteDat()把结果输出到文件out.dat中。
    提示:若中间变量为PROtemp,则可以直接使用结构赋值语句进行解题。
    例如:sell[i]=temp;
    请勿改动主函数main()、读函数ReadDat()和输出函数WriteDat()的内容。
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define MAX 100
    typedef struer
    {
    char dm[5]; /*产品代码*/
    char mc[11]; /*产品名称*/
    int dj; /*单价*/
    int sl; /*数量*/
    long je; /*金额*/
    }PRO;
    PRO sell[MAx];
    void ReadDat();
    void WriteDat();
    void SortDat()
    {
    }
    void main()
    {
    memset(sell, 0, sizeof(sell));
    ReadDat();
    SortDat();
    WriteDat();
    }
    void ReadDat()
    {
    FILE *fp;
    char str[80], ch[11];
    int i;
    fp=fopen('in.dat', 'r');
    for(i=0; i<100; i++)
    {
    fgets(str, 80, fp);
    memcpy(sell[i].dm, str, 4);
    memcpy(sell[i].mc, str+4, 10);
    memcpy(ch, str+14, 4); ch[4]=0;
    sell[i].dj=atoi(ch);
    memcpy(ch, str+18, 5); ch[5]=0;
    sell[i].sl=atoi(ch);
    sell[i].je=(long)sell[i].dj*sell[i].sl;
    }
    fclose(fp);
    }
    void WriteDat()
    {
    FILE *fp;
    int i;
    fp=fopen('out.dat', 'w');
    for(i=0;i<100;i++)
    {
    fprintf(fp, '%s %s %4d %5d %10ld\n', sell[i].dm, sell[i].mc, sell[i].dj, sell[i].sl,
    sell[i].je);
    }
    fclose(fp);
    }
 
【正确答案】int i, j, len; PRO tmp; len=sizeof(tmp); memset((PRO*)&tmp, 0, len); /*按产品名称从小到大进行排列,若产品名称相同,则按金额从小到大进行排列*/ for(i=0; i<100; i++) for(j=i+1; j<100; j++) { /*若sell[i]产品名称大于sell[j]产品名称或两者相同且sell[i]金额大于sell[j]金额,则两者互换*/ if(strcmp(sell[i].mc, sell[j].mc)>0 || (sell[i].je > sell[j].je && strcmp(sell[i].mc, sell[j].mc)==0)) { memcpy((PRO*) & tmp, (PRO*) & sell[i], len); memcpy((PRO*) & sell[i], (PRO*) & sell[j], len); memcpy((PRO*) & sell[j], (PRO*) & tmp, len); } }
【答案解析】计算金额,按产品名称从小到大进行排列,相同的则按金额从小到大排列,结果存入结构数组。 通过审题可以发现主要是排序条件的设置要求有所不同,参考答案的第8行进行修改即可。
问答题   已知数据文件in.dat中存有300个四位数,并已调用读函数readDat()把这些数存入数组a中,请编制一函数jsValue(),其功能是:求出千位数上的数加个位数上的数等于百位数上的数加十位数上的数的个数cnt,再把所有满足此条件的四位数依次存入数组b中,然后对数组b的四位数按从小到大的顺序进行排序。最后main()函数调用写函数writeDat()把数组b中的数输出到文件out.dat中。
    例如:6712,6+2=7+1,则该数满足条件存入数组b中,且个数cnt=cnt+1。
    8129,8+9!=1+2,则该数不满足条件忽略。
    程序中已定义数组:a[300],b[300],已定义变量:cnt
    请勿改动数据文件in.dat中的任何数据、主函数main()、读函数readDat()和写函数writeDat()的内容。
    #include <stdio.h>
    int a[300], b[300], cnt=0;
    void writeDat();
    void readDat();
    void jsValue()
    {
    }
    main()
    {
    int i;
    readDat();
    jsValue();
    writeDat();
    printf('cnt=%d\n', cnt);
    for(i=0; i<cnt; i++)
    printf('b[%d]=%d\n', i, b[i]);
    }
    void readDat()
    {
    FILE *fp;
    int i;
    fp=fopen('in.dat', 'r');
    for(i=0; i<300; i++)
    fscanf(fp, '%d,', &a[i]);
    fclose(fp);
    }
    void writeDat()
    {
    FILE *fp;
    int i;
    fp=fopen('out.dat', 'w');
    fprintf(fp, '%d\n', cnt);
    for(i=0; i<cnt; i++)
    fprintf(fp, '%d\n', b[i]);
    fclose(fp);
    }
 
【正确答案】int i, j, qw, bw, sw, gw, tmp; for(i=0; i<300; i++) { qw=a[i]/1000; bw=(a[i]-qw*1000)/100; sw=(a[i]-qw*1000-bw*100)/10; gw=a[i]%10; if(qw+gw-bw-sw==0) //如果a[i]千位上数加上其个位上的数减去其百位上的数减去其十位上的数等于0 b[cnt++]=a[i]; } for(i=0; i<cnt-1; i++) for(j=i+1; j<cnt; j++) if(b[i]>b[j]) { tmp=b[j]; b[j]=b[i]; b[i]=tmp; }
【答案解析】千位+个位等于百位+十位个数,把所有满足此条件的数依次存入数组,按从小到大的顺序排序。 通过审题可以发现仅有一个不同点,即要求统计的四位数的条件是“个位+千位=百位+十位”,参考答案的第8条语句,修改if条件语句的判断条件即可,对于数据交换的整型变量tmp可以自定义其变量名。