最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,Web服务器压力也不是很大的情况下,前台页面访问却很慢,看有没有办法充分利用数据库服务器的性能,于是做了一个单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试。

测试环境:

  • CPU:Inter Core2 Quad,Q8300,2.50GHz;
  • 内存:4.00GB
  • 系统:Windows 7 32位系统
  • 数据库系统:SqlServer 2008,有两个实例,一个是默认实例,一个是命名实例QE2

测试数据:

67万真实的基金收益数据,将这个表的数据放到了3个数据库中,详细内容见下面的连接字符串配置:

    <add name ="Ins1_DB1" connectionString ="Data Source=.;Initial Catalog=TestDB;Integrated Security=True"/>
    <add name ="Ins1_DB2" connectionString ="Data Source=.;Initial Catalog=LocalDB;Integrated Security=True"/>
    <add name ="Ins2_DB" connectionString ="Data Source=.\QE2;Initial Catalog=TestDB;Integrated Security=True"/>

测试内容:

首先筛选出表中所有的基金代码,然后统计每只基金的最新收益率日期,对应的T-SQL代码如下:

    
  declare @max_fsrq datetime
  declare @currJJDM varchar(10)
  declare @temp table (jjdm2 varchar(10))
  declare @useTime datetime
  set @useTime =GETDATE ();
  
  insert into @temp(jjdm2)
   select jjdm from [FundYield] group by jjdm order by jjdm asc
   
  while EXISTS (select jjdm2 from @temp)
  begin
    set @currJJDM=(select top 1 jjdm2 from @temp)
    select @max_fsrq = MAX(fsrq) from [FundYield] where jjdm=@currJJDM
    delete from @temp where jjdm2 =@currJJDM 
    print @max_fsrq
  end

print 'T-SQL Execute Times(ms):'  
 print datediff(ms,@useTime,getdate())

直接执行这个T-SQL脚本,在数据库表没有索引的情况下,耗费的时间是:

T-SQL Execute Times(ms):
58796

根据这个功能,写了一个.net控制台程序来测试,测试程序没有使用任何数据访问框架,直接使用ADO.NET,下面是多线程测试的代码,其它代码略:

 public static void Test2(string connName1,string connName2)
        {
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            string allJjdmList = "";
            string connString = getConnectionString();
            //SqlConnection conn = new SqlConnection(connString);
            //conn.Open();

string sql = "select jjdm from [FundYield] group by jjdm order by jjdm asc";
            DataSet ds = getData(connString, sql);
            int allCount = ds.Tables[0].Rows.Count;
            int p = (int)(allCount * 0.5);

System.Threading.Thread t1=new System.Threading.Thread (new System.Threading.ParameterizedThreadStart (tp1=>
                {
                    for (int i = 0; i < p; i++)
                    {
                        string jjdm = ds.Tables[0].Rows[i][0].ToString();

object result = getSclar(ConfigurationManager.ConnectionStrings[connName1].ConnectionString,
                       string.Format("select MAX(fsrq) from [FundYield] where jjdm='{0}'", jjdm));
                        if (result != DBNull.Value)
                        {
                            DateTime dt = Convert.ToDateTime(result);
                            //Console.WriteLine("Thread 2 No {0} ,jjdm[{1}] last FSRQ is:{2}", i, jjdm, dt);
                        }

allJjdmList = allJjdmList + "," + jjdm;
                    }

Console.WriteLine("Tread 1 used all time is(ms):{0}", watch.ElapsedMilliseconds);
                }
            ));

System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(tp2 =>
            {
                for (int i = p; i < allCount; i++)
                {
                    string jjdm = ds.Tables[0].Rows[i][0].ToString();
                    //这里不论使用default还是express,区别不大
                    object result = getSclar(ConfigurationManager.ConnectionStrings[connName2].ConnectionString,
                        string.Format("select MAX(fsrq) from [FundYield] where jjdm='{0}'", jjdm));
                    if (result != DBNull.Value)
                    {
                        DateTime dt = Convert.ToDateTime(result);
                        //Console.WriteLine("Thread 2 No {0} ,jjdm[{1}] last FSRQ is:{2}", i, jjdm, dt);
                    }
                    
                    allJjdmList = allJjdmList + "," + jjdm;
                }

Console.WriteLine("Tread 2 used all time is(ms):{0}", watch.ElapsedMilliseconds);
            }
            ));

t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();

Console.WriteLine("====All thread completed!========");

}

下面是测试结果:

第一次,数据库没有创建索引,进行全表扫描:

------单数据库,单线程测试---------
used all time is(ms):59916
------同一实例,双数据库,单线程测试---------
used all time is(ms):59150
------同一实例,双数据库,多线程测试---------
Tread 2 used all time is(ms):51223
Tread 1 used all time is(ms):58175
====All thread completed!========
------双实例,双数据库,单线程测试---------
used all time is(ms):58230
------双实例,双数据库,多线程测试---------
Tread 2 used all time is(ms):52705
Tread 1 used all time is(ms):58293
====All thread completed!========

第二次,数据库响应的字段创建索引,下面是测试结果:

------单数据库,单线程测试---------
used all time is(ms):1721
------同一实例,双数据库,单线程测试---------
used all time is(ms):1737
------同一实例,双数据库,多线程测试---------
Tread 2 used all time is(ms):1684
Tread 1 used all time is(ms):1714
====All thread completed!========
------双实例,双数据库,单线程测试---------
used all time is(ms):1874

------单数据库,单线程测试---------
used all time is(ms):1699
------同一实例,双数据库,单线程测试---------
used all time is(ms):1754
------同一实例,双数据库,多线程测试---------
Tread 1 used all time is(ms):1043
Tread 2 used all time is(ms):1103
====All thread completed!========
------双实例,双数据库,单线程测试---------
used all time is(ms):1838
------双实例,双数据库,多线程测试---------
Tread 1 used all time is(ms):1072
Tread 2 used all time is(ms):1139
====All thread completed!========

测试结论:

综合全表扫描访问和有索引方式的访问,

单线程访问:

  • 在同一个数据库实例上,双数据库没有体现出优势,甚至单数据库稍微优胜于多数据库;
  • 在两个数据库实例上,双实例双实例要落后于单实例单数据库;

多线程访问:

  • 双数据库实例稍微落后于单数据库实例;

综合结论,看来不论是双数据库还是双实例,对比与单实例或者单数据库,都没有体现出优势,看来前者的优势不在于访问效率,一位朋友说,数据库实例是不同的服务,控制粒度更小,维护影响比较低。但我想,双数据库实例,双数据库,多核CPU,应该跟两台数据库服务器差不多的性能吧,怎么没有体现优势呢?也许是我的测试机器仅仅有一个磁盘,这里磁盘IO成了瓶颈。

这个测试有没有意义,或者这个结果的原因,还请大牛们多多指教!

--------------------------------------------------------------

意外发现:

1,有人说频繁的查询在完全数据库中进行效率最高,测试发现,在查询分析器上直接运行上面的那个T-SQL脚本,跟程序从数据库取出数据,再加工计算查询,效率上没有明显的区别,所以哪些支持“将复杂的业务逻辑写在存储过程中效率最高的观点是站不住脚的!”  ,ADO.NET从数据库来回操作数据一样有效率,如果加上复杂的字符函数计算和大批量的循环操作,存储过程的效率不一定高。

2,在使用程序进行频繁的数据库操作的时候,使用一个连接对象还是在每个方法中使用新的连接对象,一直是很纠结的问题,心想频繁的数据操作还是用一个连接对象快吧?在本文给出的测试代码中,有下列语句:

//SqlConnection conn = new SqlConnection(connString);
            //conn.Open();
注释掉这些语句,在被调用的方法中使用自己的连接对象,与取消注释,全部使用一个连接对象,效率上没有任何区别!

究其原因,可能是ADO.NET自动使用了连接池,实际上程序在不同的情况下,使用的都是一个连接,所以操作上效率没有区别。

后续测试

在真正的服务器上进行测试,发现测试结论又不一样,我们有服务器A,拥有16个核,32G内存,另外一台服务器B,拥有8个核,16G内存。在服务器A上有一个SqlServer实例,两个一样的数据库;在在服务器B上有一个SqlServer实例,一个数据库,下面是测试结果:

------单数据库,单线程测试---------
used all time is(ms):650
------同一实例,双数据库,单线程测试---------
used all time is(ms):418
------同一实例,双数据库,多线程测试---------
Tread 2 used all time is(ms):221
Tread 1 used all time is(ms):223
====All thread completed!========
------双实例,双数据库,单线程测试---------
used all time is(ms):1283
------双实例,双数据库,多线程测试---------
Tread 1 used all time is(ms):228
Tread 2 used all time is(ms):542
====All thread completed!========

可以看到,同一实例,多数据库,还是有明显的优势,而多线程优势更大;由于两台服务器性能差距较大,双实例测试没有显示出优势,但多线程下还是比单实例单数据库好!

为什么PC机跟服务器测试的结论不一致?也许还是跟计算能力相关,PC机的计算负载太大,已经失去了测试的意义。

本文转自深蓝医生博客园博客,原文链接:http://www.cnblogs.com/bluedoctor/archive/2011/06/28/2092113.html,如需转载请自行联系原作者

单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试相关推荐

  1. innodb实例损坏情况下恢复数据及相关工具的开发

    作者介绍:谢浩,现任职于云和恩墨(北京)信息技术有限公司,具有多年oracle数据库企业级运维经验,擅长结合业务.硬件系统制定各种项目方案,具有丰富mysql相关的工作经验. 假设你在使用MySQL中 ...

  2. java怎么复制别人的数据库_java-如何在不使用Apache DDLUtils的情况下使用JDBC将模式从一个数据库复制到另一个数据库?...

    我在MySQL中有一个数据库,我想以编程方式在FileMaker Pro中创建所有相同的表和字段.我可以使用JDBC自己完成此操作,但我希望已经有了可以执行此操作的库. 我研究了来自Apache的DD ...

  3. hibernate映射数据库表如何在不插入值的情况下使表中字段默认值生效

    问题描述:    hibernate技术中对应数据库中每一个表,都会有一个映射文件与之对应,此文件描述数据库表中每一个字段的类型.长度.是否可空等属性.在进行表中记录的插入(更新)操作时,hibern ...

  4. form表单提交既有文字也有图片的情况下,增加enctype属性

    <!--当文件提交有文字和图片的时候,form表单属性中要加上enctype--> <form action="" method="post" ...

  5. 【黄啊码】MySQL入门—17、在没有备份的情况下,如何恢复数据库数据?

    大家好!我是黄啊码,MySQL的入门篇已经讲到第16个课程了,今天我们继续讲讲大白篇系列--科技与狠活之恢复数据库 在没做数据库备份,没有开启使用 Binlog 的情况下,尽可能地找回数据. 今天的内 ...

  6. KingbaseES数据库概念(二)--数据访问

    目录 1. SQL 1.1. SQL简介 1.2. SQL语句概述 1.3. 优化器概述 1.4. SQL处理概述 2. PLSQL 2.1. 服务器端编程简介 2.2. PL/SQL概述 2.3.  ...

  7. 『数据库』数据库编程(概念性的东西,应用一般,甚至有点过时,用来考试)

    数据库从入门到精通:戳我 嵌入式SQL SQL语言提供了两种不同的使用方式 交互式 嵌入式 为什么要引入嵌入式SQL SQL语言是非过程性语言 事务处理应用需要高级语言 这两种方式细节上有差别,在程序 ...

  8. SQL Server系统数据库–模型数据库

    介绍 (Introduction) This is my fourth article about SQL Server system databases. In previous articles ...

  9. mysql数据库 安装后 闪_MYSQL数据库Mysql数据库安装完成后需要进行的6个后续操作...

    <MYSQL数据库Mysql数据库安装完成后需要进行的6个后续操作>要点: 本文介绍了MYSQL数据库Mysql数据库安装完成后需要进行的6个后续操作,希望对您有用.如果有疑问,可以联系我 ...

  10. 【数据库】数据库编程

    嵌入式SQL SQL语言提供了两种不同的使用方式 交互式 嵌入式 为什么要引入嵌入式SQL SQL语言是非过程性语言 事务处理应用需要高级语言 这两种方式细节上有差别,在程序设计的环境下,SQL语句要 ...

最新文章

  1. javascript的数值范围
  2. C++常用数据结构入门
  3. response html 页面,使用response将html拼接页面写到当前浏览器端完成自动提交功能...
  4. 数据结构---哈夫曼树
  5. [NodeJs] 你有使用过npx吗?它主要解决什么问题?
  6. Win11如何开启旧版组件 Win11开启旧版组件的方法
  7. C++ 类和对象成员特性
  8. imp 只导入索引_Elasticsearch系列---实战零停机重建索引
  9. 深入理解ARM体系架构(S3C6410)---arm7,arm9,arm11区别
  10. 【源码阅读】看Spring Boot如何自动装配ActiveMQ收发组件
  11. java玻璃效果_swing透明效果(没aero毛玻璃那么好看)
  12. iptables(3)
  13. JavaScript 中的事件对象(读书笔记思维导图)
  14. atitit。ocr框架类库大全 attilax总结
  15. Android native memory leak detect (Android native内存泄露检测)
  16. 软件测试:Lab 2 Selenium
  17. mysql.sock连接_解决不能通过mysql.sock连接MySQL问题的办法
  18. RocketMQ 学习方法之我见
  19. 清理数据 python_使用python的数据清理技术
  20. 对于流媒体的一些认识

热门文章

  1. HackMyvm(六)Noob持续更新
  2. 【ACM-ICPC 2018 北京赛区网络预赛】B题Tomb Raider ---- 状态压缩+思维★
  3. eclipse 中各种小图标含义
  4. 小心,Android木马工具SpyNote免费啦!远程监听就是这么简单
  5. 梁宁增长思维30讲笔记 - 模式
  6. photoshop cs6中画虚线的设置
  7. PCIE实现PIO模式寄存器读写调试记录
  8. 麻省理工公开课:线性代数视频总结(课1-2)
  9. 计算机时区找不到北京,电脑时区里为何没有标准北京时间
  10. 1-7-2 查询水果价格分数