关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » SQL语言 »单数据库vs多数据库,单实例vs多实例 效率测试(1)

    单数据库vs多数据库,单实例vs多实例 效率测试(1)

    2011-06-29 14:01:00 出处:ITJS
    分享

    最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,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

    最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,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

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    帝国CMS7.5编辑器上传图片取消宽高的三种方法

    帝国cms如何自动生成缩略图的实现方法

    Windows 12即将到来,将彻底改变人机交互

    帝国CMS 7.5忘记登陆账号密码怎么办?可以phpmyadmin中重置管理员密码

    帝国CMS 7.5 后台编辑器换行,修改回车键br换行为p标签

    Windows 11 版本与 Windows 10比较,新功能一览

    Windows 11激活产品密钥收集及专业版激活方法

    IT头条

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    严重缩水!NVIDIA将推中国特供RTX 5090 DD:只剩24GB显存

    00:17

    无线路由大厂 TP-Link突然大裁员:补偿N+3

    02:39

    Meta 千万美金招募AI高级人才

    00:22

    技术热点

    微软已修复windows 7/windows 8.1媒体中心严重漏洞 用户可下载安

    卸载MySQL数据库,用rpm如何实现

    windows 7中使用网上银行或支付宝支付时总是打不开支付页面

    一致性哈希算法原理设计

    MySQL数字类型中的三种常用种类

    如何解决SQL Server中传入select语句in范围参数

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。