34,590
社区成员
发帖
与我相关
我的任务
分享
*** 测试数据***/
数据量20w,
左连接获取,
主表tb2
CREATE TABLE [tb2] (
[id] [bigint] IDENTITY (1, 1) NOT NULL ,
[tb1_id] [bigint] NULL ,
[type] [int] NULL ,
CONSTRAINT [PK_tb2] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
) ON [PRIMARY]
GO
从表 tb1
CREATE TABLE [tb1] (
[ID] [bigint] IDENTITY (1, 1) NOT NULL ,
[testname] [char] (10) COLLATE Chinese_PRC_CI_AS NULL ,
[stoploss] [int] NULL ,
[stopprofit] [int] NULL ,
CONSTRAINT [PK_tb1] PRIMARY KEY CLUSTERED
(
[ID]
) ON [PRIMARY]
) ON [PRIMARY]
GO
两者的关系,多对一, 简单来说 就是2对一.
/****以一条关联数据为例***/
--tb2
id tb1_id type
1 1 101(指向tb2的stoploss 字段)
2 1 102(指向tb2的stopprofit字段)
--tb1
id testname stoploss stopprofit
1 test 3 5
/****以一条关联数据为例***/
/// <summary>
/// 获取消耗时间
/// 2010-1-13 by ascor
/// </summary>
/// <param name="strSql"></param>
/// <returns></returns>
private TimeSpan getTime(string strSql)
{
GC.Collect();
GC.WaitForPendingFinalizers();
DateTime dt = DateTime.Now;
DataSet ds = Query(strSql);
TimeSpan ts = DateTime.Now - dt;
return ts;
}
/// <summary>
/// 执行查询语句,返回DataSet
/// 2010-1-13 by ascor
/// </summary>
/// <param name="SQLString">查询语句</param>
/// <returns>DataSet</returns>
public DataSet Query(string SQLString)
{
using (SqlConnection connection = new SqlConnection(strconnect))
{
DataSet ds = new DataSet();
try
{
connection.Open();
SqlDataAdapter command = new SqlDataAdapter(SQLString, connection);
command.Fill(ds, "ds");
}
catch (SqlException ex)
{
throw new Exception(ex.Message);
}
finally
{
connection.Close();
}
return ds;
}
}
//测试方法1,全部字段获取
protected void Button1_Click(object sender, EventArgs e)
{
StringBuilder strSql = new StringBuilder();
strSql.Append(@"select a.id,b.id,b.testname,b.stoploss,b.stopprofit, a.type
from tb2 a left join tb1 b
on a.tb1_id=b.id");
this.lbl_function1.Text = getTime(strSql.ToString()).ToString();
}
//测试方法2,使用case获取需要字段
protected void Button2_Click(object sender, EventArgs e)
{
StringBuilder strSql = new StringBuilder();
strSql.Append(@"select a.id,b.id,b.testname,a.type,case a.type when 101 then b.stoploss when 102 then b.stopprofit end params
from tb2 a left join tb1 b
on a.tb1_id=b.id");
this.lbl_function2.Text = getTime(strSql.ToString()).ToString();
}
/*****测试结果*****/
方法2始终比方法1测试快0.05秒-0.1秒范围内
粗劣一看,方法1获取多了一个字段, 但是方法2的select在每次读取记录的时候都是多了一次判断操作.虽然有聚索引, 但是因为没有使用where, 这两种方法的获取应该都是堆获取.不存在二叉树的获取方式,也就是说两种获取方式每次获取应该是顺序获取的.不同的是方法2在读取的时候多了一个判断, 我猜想方法2快的原因是不是,判断完后调用(或者说借用)了索引直接指向了说需要的字段.... 只是猜测, 还望有谁可以告诉我真正的原因
附加测试.
/***测试代码**/
//方法5
protected void Button5_Click(object sender, EventArgs e)
{
StringBuilder strSql = new StringBuilder();
strSql.Append(@"select a.*
from tb2 a where a.id>0");
this.lbl_function5.Text = getTime(strSql.ToString()).ToString();
}
//方法6
protected void Button6_Click(object sender, EventArgs e)
{
StringBuilder strSql = new StringBuilder();
strSql.Append(@"select a.*
from tb2 a ");
this.lbl_function6.Text = getTime(strSql.ToString()).ToString();
}
/**** 测试结果***/
根据我对索引的理解, 理论上说方法5应该比方法6快.
因为在没有使用where进行检索数据的时候, 所有的读取是不依靠索引的, 直接堆获取,这是根据msdn的sql上对索引的解释得来的分析, .但是事实结果是 方法5与6的读取速度是完全一样的.
这两个测试结果 ,我都很郁闷,跟我理解的有出入, 望高人可以给我解释一下.. 代码有点长,且冗余,请慢慢看!
个人认为:
方法1比方法2要多返回一些字段的数据,应该1比2要慢一些,
但又因为2比1多一些逻辑判断操作。所以在这个地方1比2要慢一点。所以从情况上来说是两者相当。
至于最后到底谁比谁快。这个就要问微软了。是返回多一个字段用的时间多,还是判断用的时间多
方法5和方法6,照常理方法5比方法6会快一些,因为方法5有条件,返回的数据应该会少一些。
但现在你tb1表中没有id<=0的数据。也就是说id>0返回了全部数据。所以跟方法6没什么区别了。。。
select a.* from tb2 a where a.id>0
select a.* from tb2 a