热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测

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

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

最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,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脚本,跟程序从数据库取出数据,再加工计算查询,效率上没有明显的区别,所以哪些支持&#8220;将复杂的业务逻辑写在存储过程中效率最高的观点是站不住脚的!&#8221; ,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机的计算负载太大,已经失去了测试的意义。

推荐阅读
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • 优化联通光猫DNS服务器设置
    本文详细介绍了如何为联通光猫配置DNS服务器地址,以提高网络解析效率和访问体验。通过智能线路解析功能,域名解析可以根据访问者的IP来源和类型进行差异化处理,从而实现更优的网络性能。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 如何配置Unturned服务器及其消息设置
    本文详细介绍了Unturned服务器的配置方法和消息设置技巧,帮助用户了解并优化服务器管理。同时,提供了关于云服务资源操作记录、远程登录设置以及文件传输的相关补充信息。 ... [详细]
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 本文详细介绍了如何使用libpq库与PostgreSQL后端建立连接。通过探讨PQconnectdb()函数的工作原理及其在实际应用中的使用方法,帮助读者理解并掌握建立高效、稳定的数据库连接的关键步骤。 ... [详细]
  • SQL中UPDATE SET FROM语句的使用方法及应用场景
    本文详细介绍了SQL中UPDATE SET FROM语句的使用方法,通过具体示例展示了如何利用该语句高效地更新多表关联数据。适合数据库管理员和开发人员参考。 ... [详细]
  • 本周信息安全小组主要进行了CTF竞赛相关技能的学习,包括HTML和CSS的基础知识、逆向工程的初步探索以及整数溢出漏洞的学习。此外,还掌握了Linux命令行操作及互联网工作原理的基本概念。 ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 解决Linux系统中pygraphviz安装问题
    本文探讨了在Linux环境下安装pygraphviz时遇到的常见问题,并提供了详细的解决方案和最佳实践。 ... [详细]
  • 本文介绍了一款用于自动化部署 Linux 服务的 Bash 脚本。该脚本不仅涵盖了基本的文件复制和目录创建,还处理了系统服务的配置和启动,确保在多种 Linux 发行版上都能顺利运行。 ... [详细]
  • 在Linux系统中配置并启动ActiveMQ
    本文详细介绍了如何在Linux环境中安装和配置ActiveMQ,包括端口开放及防火墙设置。通过本文,您可以掌握完整的ActiveMQ部署流程,确保其在网络环境中正常运行。 ... [详细]
author-avatar
不必在乎外貌涝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有