一、问题
网上流传着各种sql选择语句优化技巧,其中就包括选择sql语句构造,包括以下几种情况:
1. select * from 表名
2. select [字段名] from 表名
3. select [数据库名].[架构名].[表名].[字段名] from 表名
表名又分为:
4.[数据库名].[架构名].[表名]
5.[架构名].[表名]
6.[表名]
网上认为2,3性能肯定好于1的性能,为了验证这个观点,本文进行了验证.以下是各种sql语句的测试情况
二、问题验证
declare @i int,@max int ,@UID int,@StartTime datetime ,@EndTime datetime,@sql varchar(3000),@tableName varchar(100)
declare @span1 varchar(30),@span2 varchar(30),@span3 varchar(30)
select @max = 100 ,@UID = 45000307 --最大测试次数 , 用户ID
select @tableName = '[TestDB].[dbo].[C_Contacts]'
select @tableName = '[dbo].[C_Contacts]'
select @tableName = '[C_Contacts]'
--测试select *
set @i=0
set @sql = 'select * from ' + @tableName + ' where UMID ='+Convert(varchar(30),@UID)
set @StartTime = GETDATE();
while(@i<@max)
begin
execute(@sql)
set @i = @i+1
end
set @EndTime = GETDATE();
set @span1 = convert(varchar(30),DATEDIFF(MS,@StartTime,@EndTime))
--测试select [字段名]
set @i=0
set @sql = 'select [ContactID],[UMID],[FirstName],[LastName],[Birthday],[Photo],[Remarks],[Ver],[InsTime],[UpdTime] from ' + @tableName + ' where UMID ='+Convert(varchar(30),@UID)
set @StartTime = GETDATE();
while(@i<@max)
begin
execute(@sql)
set @i = @i+1
end
set @EndTime = GETDATE();
set @span2 = convert(varchar(30),DATEDIFF(MS,@StartTime,@EndTime))
--测试select [数据库名].[架构名].[表名].[字段名]
set @i=0
set @sql = 'select [dbo].[C_Contacts].[ContactID],[dbo].[C_Contacts].[UMID],[dbo].[C_Contacts].[FirstName],[dbo].[C_Contacts].[LastName],[dbo].[C_Contacts].[Birthday],[dbo].[C_Contacts].[Photo],[dbo].[C_Contacts].[Remarks],[dbo].[C_Contacts].[Ver],[dbo].[C_Contacts].[InsTime],[dbo].[C_Contacts].[UpdTime] from ' + @tableName + ' where UMID ='+Convert(varchar(30),@UID)
set @StartTime = GETDATE();
while(@i<@max)
begin
execute(@sql)
set @i = @i+1
end
set @EndTime = GETDATE();
set @span3 = convert(varchar(30),DATEDIFF(MS,@StartTime,@EndTime))
print '测试select * 处理完成!共耗时: ' + @span1 +' ms'
print '测试select [字段名] 处理完成!共耗时: ' + @span2 +' ms'
print '测试select [数据库名].[架构名].[表名].[字段名] 处理完成!共耗时: ' + @span3 +' ms'
print '----------------------------'
print @span1
print @span2
print @span3
三、结果
每种情况分别测试5次,取平均值,得到以下的结果:
表名 | select语句 | 第1次 | 第2次 | 第3次 | 第4次 | 第5次 | 平均值 |
[数据库名].[架构名].[表名] | 测试select * | 4166 | 4340 | 4260 | 4246 | 4216 | 4245.6 |
测试select [字段名] | 4816 | 4946 | 4756 | 4793 | 4853 | 4832.8 | |
测试select [数据库名].[架构名].[表名].[字段名] | 5523 | 5293 | 5533 | 5213 | 5290 | 5370.4 | |
[架构名].[表名] | 测试select * | 4576 | 4193 | 4326 | 4206 | 4226 | 4305.4 |
测试select [字段名] | 5030 | 4860 | 4806 | 4920 | 4803 | 4883.8 | |
测试select [数据库名].[架构名].[表名].[字段名] | 5266 | 5173 | 5413 | 5156 | 5253 | 5252.2 | |
[表名] | 测试select * | 4516 | 4206 | 4250 | 4203 | 4293 | 4293.6 |
测试select [字段名] | 4780 | 4766 | 4880 | 4790 | 4870 | 4817.2 | |
测试select [数据库名].[架构名].[表名].[字段名] | 5276 | 5446 | 5370 | 5270 | 5240 | 5320.4 |
四、结论
1.直接使用select * 比使用select [字段名] 和 测试select [数据库名].[架构名].[表名].[字段名] 性能要好.
2.select语句中的表名用[数据库名].[架构名].[表名]的形式,比用[表名] 和 [架构名].[表名] 性能要好.
五、原因分析
1.select语句中加入数据名,架构名会加大sql语句的长度,sql编译时会增加复杂度,所以时间偏长.
2.表名用[数据库名].[架构名].[表名]编译时可以减少表名匹配的时间,所以时间较少.
不知道我的分析有无道理,也不知道数据内部对sql脚本的处理及编译是怎样的一个流程,期待高手作答.