2012-03-28 41 views
6

我想知道下面两种方法是否有任何性能差异。 基本上,问题是我们允许ID中的空格和破折号,但是某些遗留应用程序无法使用这些空间和破折号,因此它们被剥离出来。 据我所见,最简单的方法是在触发器或作为一个调整列。 SQL显示如下(清除并匿名,所以如果出现错误,请致歉) 到目前为止,在我们的测试服务器上,两种方法之间似乎没有任何区别,其他人是否有任何输入?而不是触发器或计算列?哪个更好?

[数据库的SQL Server 2008] [查找表20000000行和生长]

选项1 - 创建触发器

CREATE TRIGGER triMem_Lkup on Mem_Lkup 
INSTEAD OF INSERT 
AS 
BEGIN 
    INSERT INTO Mem_lkup 
     SELECT ex_id, contact_gid, id_type_code, date_time_created, 
       (replace(replace([ex_id],' ',''),'-','')) as ex_id_calc 
     FROM inserted 
END 
GO 

对战 选项2 - 使用计算列

CREATE TABLE [dbo].[Mem_lkup](
    [mem_lkup_sid] [int] IDENTITY(1,1) NOT NULL, 
    [ex_id] [varchar](18) NOT NULL, 
    [contact_gid] [int] NOT NULL, 
    [id_type_code] [char] (1) NOT NULL, 
    [date_time_created] [datetime] NOT NULL, 
    [ex_id_calc] AS CAST(replace(replace([ex_id],' ','') ,'-','') AS varchar(18)) PERSISTED 

    CONSTRAINT [PK_Mem_Lkup] PRIMARY KEY NONCLUSTERED 
(
    [mem_lkup_sid] ASC 
) 

哪一个最好?

回答

4

计算列将是最好的。

INSTEAD OF触发器将首先在tempdb中创建整个伪inserted表。

Plan

对于触发版本与您CREATE TABLE声明(上堆非集群PK)

SET STATISTICS IO ON; 

INSERT INTO [_test].[dbo].[Mem_lkup] 
      ([ex_id] 
      ,[contact_gid] 
      ,[id_type_code] 
      ,[date_time_created]) 
SELECT type AS [ex_id] 
     ,1 [contact_gid] 
     ,'A' [id_type_code] 
     ,getdate() [date_time_created] 
    FROM master..spt_values 

给我

Table 'Worktable'. Scan count 0, logical reads 5076 
Table 'spt_values'. Scan count 1, logical reads 15 

Table 'Mem_lkup'. Scan count 0, logical reads 7549 
Table 'Worktable'. Scan count 1, logical reads 15 

而计算列的版本相似,但可避免worktable读取。

Table 'Mem_lkup'. Scan count 0, logical reads 7555 
Table 'spt_values'. Scan count 1, logical reads 15 

你有什么理由坚持这个价值吗? (而不是有一个非持久的计算列)

+0

我认为我需要坚持计算的列,因为它正在被用作索引的一部分。 (http://msdn.microsoft.com/en-us/library/ms189292.aspx#BKMK_persisted) 这是不正确的? – 2012-03-29 08:44:59

+0

@EoinO - 没有。不适用于这种情况,仅适用于不精确(浮点)值或CLR函数/类型。 – 2012-03-29 15:45:27

+1

感谢@Martin,你的回答真的很翔实! Re:持续评论,如果你正在运行成千上万的记录,这个值是否会每次计算? – 2012-04-04 16:50:35