tsql 和 clr 的性能实测比对(转)
//************* C# clr user defined type:
using System;
using System.Data;
using System.Runtime.InteropServices;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
namespace MyTestNameSpace
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[Microsoft.SqlServer.Server.SqlUserDefinedType(Format.Native, IsByteOrdered = true, ValidationMethodName = "Validate")]
public class Test1 : INullable
{
public Test1()
{
m_Null = false;
}
public Test1(int city, int level, int age1, int age2, bool extra)
{
City = city;
Level = level;
Age1 = age1;
Age2 = age2;
Extra = extra;
m_Null = false;
}
[SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static Test1 NewTest1(int city, int level, int age1, int age2, bool extra)
{
return new Test1(city, level, age1, age2, extra);
}
[SqlMethod(DataAccess = DataAccessKind.None, InvokeIfReceiverIsNull = false, IsPrecise = true, IsDeterministic = true, OnNullCall = false)]
public bool Check(int city, int level, int age, bool extra)
{
if (city == this.City &&
level > this.Level &&
age >= this.Age1 &&
age <= this.Age2 &&
extra == this.Extra)
return true;
else
return false;
}
public override string ToString()
{
// Replace the following code with your code
return "";
}
public bool IsNull
{
get
{
// Put your code here
return m_Null;
}
}
public static Test1 Null
{
get
{
Test1 h = new Test1();
h.m_Null = true;
return h;
}
}
public static Test1 Parse(SqlString s)
{
return Null;
}
public bool Validate()
{
return true;
}
public int Age1;
public int Age2;
public int Level;
public int City;
public bool Extra;
private bool m_Null;
}
}
//************* C# clr user defined type end
--****** --Creating the assembly
-- note: replace with your own path and/or name
CREATE ASSEMBLY [MyTestAsm]
FROM 'MyTestAsm.dll'
WITH PERMISSION_SET = SAFE
GO
CREATE TYPE [dbo].[Test1]
EXTERNAL NAME [MyTestAsm].[MyTestNameSpace.Test1]
go
Create FUNCTION [dbo].[NewTest1](@city [int], @level [int], @age1 [int], @age2 [int], @extra [bit])
RETURNS [dbo].[Test1] WITH EXECUTE AS CALLER
AS
EXTERNAL NAME [MyTestAsm].[MyTestNameSpace.Test1].[NewTest1]
go
--****** create table
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Test](
[OID] [int] IDENTITY(1,1) NOT NULL,
[City] [int] NOT NULL,
[Age] [int] NOT NULL,
[Level] [int] NOT NULL,
[Extra] [int] NOT NULL,
[SCity] [int] NOT NULL,
[SAge1] [int] NOT NULL,
[SAge2] [int] NOT NULL,
[SLevel] [int] NOT NULL,
[SExtra] [int] NOT NULL,
[Data] [dbo].[Test1] NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[OID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
-- SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[TestClr]
@oid int
AS
BEGIN
declare @scity int, @sage1 int, @sage2 int, @slevel int, @sextra bit
declare @data dbo.Test1
SET NOCOUNT ON;
select @data = data from dbo.test where oid = @oid
select oid, age, city, extra, level from dbo.test
where @data.[Check](city, level, age, extra) = 1
END
go
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[Testsproc]
@oid int
AS
BEGIN
declare @scity int, @sage1 int, @sage2 int, @slevel int, @sextra bit
SET NOCOUNT ON;
select @scity = scity, @sage1 = sage1, @sage2 = sage2, @slevel = slevel,
@sextra = sextra from dbo.test where oid = @oid
select oid, age, city, extra, level from dbo.test
where level > @slevel and city = @scity
and extra = @sextra and age >= @sage1 and age <= @sage2
END
go
--****** populate with test data
declare @count int
declare @range int
declare @sage1 int, @sage2 int, @slevel int, @scity int, @sextra bit
set @count = 10000
set @range = 10
begin tran -- importanct without this, it takes much longer to ron
while @count > 0
begin
set @sage1 = rand() *@range
set @sage2 = @sage1 + rand() *@range
set @slevel = rand() *@range
set @scity = rand() *@range
set @sextra = case when rand()>0.5 then 1 else 0 end
INSERT INTO Test
(Age, City, Extra, Level, SAge1, Sage2, SLevel, SCity, SExtra, Data)
VALUES (rand()*@range, rand()*@range, case when rand()>0.5 then 1 else 0 end , rand() * @range,
@SAge1,@Sage2,@SLevel,@SCity,@SExtra, dbo.NewTest1(@SCity,@SLevel, @SAge1,@Sage2,@SExtra ))
set @count = @count -1
end
commit
go
--****** performance test for tsql
declare @count int
declare @oid int
declare @inc int
declare @date1 datetime, @date2 datetime
set @count = 40
set @inc = 33
set @date1= getdate()
select @oid = min(oid) from dbo.test
while @count > 0
begin
set @oid = @oid + @inc
exec dbo.Testsproc @oid
set @count = @count -1
end
set @date2 = getdate()
print datediff(ms, @date1, @date2)
go
--****** performance test for clr
declare @count int
declare @oid int
declare @inc int
declare @date1 datetime, @date2 datetime
set @count = 40
set @inc = 33
set @date1= getdate()
select @oid = min(oid) from dbo.test
while @count > 0
begin
set @oid = @oid + @inc
exec dbo.TestClr @oid
set @count = @count -1
end
set @date2 = getdate()
print datediff(ms, @date1, @date2)
go