单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试
最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,Web服务器压力也不是很大的情况下,前台页面访问却很慢,看有没有办法充分利用数据库服务器的性能,于是做了一个单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试。
测试环境:
- CPU:Inter Core2 Quad,Q8300,2.50GHz;
- 内存:4.00GB
- 系统:Windows 7 32位系统
- 数据库系统:SqlServer 2008,有两个实例,一个是默认实例,一个是命名实例QE2
测试数据:
67万真实的基金收益数据,将这个表的数据放到了3个数据库中,详细内容见下面的连接字符串配置:
<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,下面是多线程测试的代码,其它代码略:
{
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,如需转载请自行联系原作者
单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试相关推荐
- innodb实例损坏情况下恢复数据及相关工具的开发
作者介绍:谢浩,现任职于云和恩墨(北京)信息技术有限公司,具有多年oracle数据库企业级运维经验,擅长结合业务.硬件系统制定各种项目方案,具有丰富mysql相关的工作经验. 假设你在使用MySQL中 ...
- java怎么复制别人的数据库_java-如何在不使用Apache DDLUtils的情况下使用JDBC将模式从一个数据库复制到另一个数据库?...
我在MySQL中有一个数据库,我想以编程方式在FileMaker Pro中创建所有相同的表和字段.我可以使用JDBC自己完成此操作,但我希望已经有了可以执行此操作的库. 我研究了来自Apache的DD ...
- hibernate映射数据库表如何在不插入值的情况下使表中字段默认值生效
问题描述: hibernate技术中对应数据库中每一个表,都会有一个映射文件与之对应,此文件描述数据库表中每一个字段的类型.长度.是否可空等属性.在进行表中记录的插入(更新)操作时,hibern ...
- form表单提交既有文字也有图片的情况下,增加enctype属性
<!--当文件提交有文字和图片的时候,form表单属性中要加上enctype--> <form action="" method="post" ...
- 【黄啊码】MySQL入门—17、在没有备份的情况下,如何恢复数据库数据?
大家好!我是黄啊码,MySQL的入门篇已经讲到第16个课程了,今天我们继续讲讲大白篇系列--科技与狠活之恢复数据库 在没做数据库备份,没有开启使用 Binlog 的情况下,尽可能地找回数据. 今天的内 ...
- KingbaseES数据库概念(二)--数据访问
目录 1. SQL 1.1. SQL简介 1.2. SQL语句概述 1.3. 优化器概述 1.4. SQL处理概述 2. PLSQL 2.1. 服务器端编程简介 2.2. PL/SQL概述 2.3. ...
- 『数据库』数据库编程(概念性的东西,应用一般,甚至有点过时,用来考试)
数据库从入门到精通:戳我 嵌入式SQL SQL语言提供了两种不同的使用方式 交互式 嵌入式 为什么要引入嵌入式SQL SQL语言是非过程性语言 事务处理应用需要高级语言 这两种方式细节上有差别,在程序 ...
- SQL Server系统数据库–模型数据库
介绍 (Introduction) This is my fourth article about SQL Server system databases. In previous articles ...
- mysql数据库 安装后 闪_MYSQL数据库Mysql数据库安装完成后需要进行的6个后续操作...
<MYSQL数据库Mysql数据库安装完成后需要进行的6个后续操作>要点: 本文介绍了MYSQL数据库Mysql数据库安装完成后需要进行的6个后续操作,希望对您有用.如果有疑问,可以联系我 ...
- 【数据库】数据库编程
嵌入式SQL SQL语言提供了两种不同的使用方式 交互式 嵌入式 为什么要引入嵌入式SQL SQL语言是非过程性语言 事务处理应用需要高级语言 这两种方式细节上有差别,在程序设计的环境下,SQL语句要 ...
最新文章
- javascript的数值范围
- C++常用数据结构入门
- response html 页面,使用response将html拼接页面写到当前浏览器端完成自动提交功能...
- 数据结构---哈夫曼树
- [NodeJs] 你有使用过npx吗?它主要解决什么问题?
- Win11如何开启旧版组件 Win11开启旧版组件的方法
- C++ 类和对象成员特性
- imp 只导入索引_Elasticsearch系列---实战零停机重建索引
- 深入理解ARM体系架构(S3C6410)---arm7,arm9,arm11区别
- 【源码阅读】看Spring Boot如何自动装配ActiveMQ收发组件
- java玻璃效果_swing透明效果(没aero毛玻璃那么好看)
- iptables(3)
- JavaScript 中的事件对象(读书笔记思维导图)
- atitit。ocr框架类库大全 attilax总结
- Android native memory leak detect (Android native内存泄露检测)
- 软件测试:Lab 2 Selenium
- mysql.sock连接_解决不能通过mysql.sock连接MySQL问题的办法
- RocketMQ 学习方法之我见
- 清理数据 python_使用python的数据清理技术
- 对于流媒体的一些认识