SQL Server存储过程的最优查询方法?

时间:2015-02-05 20:12:58

标签: sql-server stored-procedures

我有5个元表具有相同的格式但依赖于其他5个表。每个Meta表都如下所示:

CREATE TABLE [dbo].[SiteMetas] 
(
    [SiteMetaId] [bigint] IDENTITY(1,1) NOT NULL,
    [SiteId] [bigint] NOT NULL,
    FOREIGN KEY([SiteId]) REFERENCES [dbo].[Sites] ([SiteId]),
    [MetaGroup] [nvarchar] (64) NOT NULL,
    [MetaName] [nvarchar] (128) NOT NULL,
    [MetaType] [char] NOT NULL DEFAULT 0, -- t, i, r, d, s, b
    [MetaBool] [bit] DEFAULT NULL, -- t
    [MetaInteger] [bigint] DEFAULT NULL, -- i
    [MetaReal] [real] DEFAULT NULL, -- r
    [MetaDateTime] [datetime] DEFAULT NULL, -- d
    [MetaString] [nvarchar] (MAX) DEFAULT NULL, -- s
    [MetaBinary] [varbinary] (MAX) DEFAULT NULL, -- b
    [MetaCreated] [datetime] NOT NULL DEFAULT (GETUTCDATE()),
    [MetaExpires] [datetime] DEFAULT NULL,
    [MetaUpdated] [datetime] DEFAULT NULL,
    PRIMARY KEY CLUSTERED ([SiteMetaId] ASC) WITH (IGNORE_DUP_KEY = ON),
    UNIQUE NONCLUSTERED ([SiteId] ASC, [MetaGroup] ASC, [MetaName] ASC) WITH (IGNORE_DUP_KEY = ON)
);

这是Site,但还有4个。像Users,...

我想从Binary读取Site元值。所以写了这个存储过程:

CREATE PROCEDURE [dbo].[GetSiteMetaBinary]
  @SiteId AS bigint,
  @Group AS nvarchar(64),
  @Name AS nvarchar(128)
AS
BEGIN
    SELECT TOP 1 [MetaBinary] 
    FROM [dbo].[SiteMetas]
    WHERE [SiteId] = @SiteId
      AND [MetaGroup] = @Group 
      AND [MetaName] = @Name 
      AND [MetaType] = 'b';
END;

此存储过程也有User的重复...以及其余表。这只是将Site替换为User。{/ p>

但是我认为我有太多这些,我写了这个:

CREATE PROCEDURE [dbo].[GetMeta]
  @Set AS nvarchar(64),
  @Id AS bigint,
  @Group AS nvarchar(64),
  @Name AS nvarchar(128),
  @Type AS nvarchar(16)
AS
BEGIN
    DECLARE @Flag nchar(1);
    DECLARE @Sql nvarchar(MAX);

    SET @Flag = CASE @Type
        WHEN 'Bool' THEN 't'
        WHEN 'Integer' THEN 'i'
        WHEN 'Real' THEN 'r'
        WHEN 'DateTime' THEN 'd'
        WHEN 'String' THEN 's'
        WHEN 'Binary' THEN 'b'
        ELSE NULL
    END;

    SET @Sql = N'SELECT TOP 1 [Meta' + @Type + N'] FROM [dbo].[' + @Set + N'Metas]' +
        N'WHERE [' + @Set + N'Id] = @Id AND [MetaGroup] = @Group AND [MetaName] = @Name AND [MetaType] = @Flag;';

    -- SELECT @Sql; -- DEBUG

    EXEC sp_executesql @Sql,
        N' @Id AS bigint, @Group AS nvarchar(64), @Name AS nvarchar(128), @Flag AS nchar(1)',
        @Id, @Group, @Name, @Flag
        ;
END;

这是一个通用的存储过程,用于根据输入参数读取存储在列中的任何类型的数据。我像[dbo].[GetMeta] 'Site', 1, 'group', 'name', 'Binary'这样使用它的不同之处在于,实际的查询是动态生成的,因此SQL Server之前就不知道它是第一个专用变体。

从性能的角度来看,哪两种选择更好,而且对SQL Server的内部结构更友好?用于每个表和列数据类型的专用数据类型,通常基于反馈参数在内部构建查询。

我也可以使用。我喜欢上一个,因为它不会污染我的存储过程空间。 :)第一个更清楚,SQL Server可能能够更好地优化它。不确定......

PS:我是SQL Server的新手

1 个答案:

答案 0 :(得分:1)

静态过程通常更快,因为SQL引擎可以缓存已编译的SP的执行计划。

然而,除非这个SP被大量召唤或者时间紧迫,否则它可能不值得担心,因为只需维持一个SP所节省的时间将弥补极少量的SP等待SP完成的时间差。