表值函数[XML Reader]非常慢 - 替代品?

时间:2011-08-12 13:49:23

标签: tsql sql-server-2008

我有以下查询真正杀死了性能,并想知道它们对xml reader子查询有什么替代方法。此查询的目的是使用某些html代码导出数据。

表数据的示例如下。

  p_s_id | p_c_id | notes
  -----------------------
     1   |   1    | this note is really long.
     2   |   1    | This is fun.
     3   |  null  | long note here 
     4   |   2    | this is not fun
     5   |   2    | this is not fun
     6   |   3    | long note here

我想拍摄具有相同p_c_id的所有不同音符并将它们连接在一起,如下所示。

可以提供任何其他信息,以便随时发表评论。

select distinct
     p_c_id
    ,'<br/><br/>'+(select distinct '&bull; ' +cast(note as nvarchar(max)) + ' <br/> '
      from dbo.spec_notes_join m2
      where m.p_c_id = m2.p_c_id
      and isnull(note,'') <> ''
      for xml path(''), type).value('.[1]', 'nvarchar(max)') as notes_spec
from dbo.spec_notes_join m

因此导出如下:

  p_c_id | notes
 --------------
    1    | <br/><br/> &bull; this note is really long.  <br/> &bull This is fun <br/>
    2    | <br/><br/> &bull; This is not fun.  <br/>
    3    | <br/><br/> &bull; long note here.   <br/>

2 个答案:

答案 0 :(得分:3)

虽然这个替代方案会跳过XML,但我不知道它是否会提高性能 - 如果你可以测试并将结果作为评论发布,我会对它进行说明。 (它在我的快速模拟中起作用,你可能需要对你自己的结构进行一些小的调试。)

从这个功能开始:

CREATE FUNCTION dbo.Testing
(
    @p_c_id  int
)
RETURNS varchar(max)
AS
 BEGIN
    DECLARE @ReturnString  varchar(max)

    SELECT @ReturnString = isnull(@ReturnString + ' <br/> , <br/><br/>&bull; ', '<br/><br/>&bull; ') + Name
     from (select distinct note
            from spec_notes_join
            where p_c_id = @p_c_id
             and isnull(note, '') <> '') xx

    SET @ReturnString = @ReturnString + ' <br/> '

    RETURN @ReturnString
 END
GO

然后将其嵌入您的查询中:

SELECT p_c_id, dbo.Testing(p_c_id)
 from (select distinct p_c_id
        from dbo.spec_notes_join) xx

由于每行所需的函数,这可能表现不佳。一个可能更快的变体是将函数编写为表值函数,并在join子句中通过CROSS APPLY引用它。

答案 1 :(得分:3)

我认为您会在外部查询中跳过distinct并获得更好的性能,而是执行group by p_c_id

select p_c_id,
      '<br/><br/>'+(select distinct '&bull; ' +cast(note as nvarchar(max)) + ' <br/> '
                    from dbo.spec_notes_join m2
                    where m.p_c_id = m2.p_c_id and 
                          isnull(note,'') <> ''
                    for xml path(''), type).value('.', 'nvarchar(max)') as notes_spec
from dbo.spec_notes_join m     
group by p_c_id

您也可以尝试与CLR User-Defined Aggregate Function连接。

其他替代方案可以在Concatenating Row Values in Transact-SQL找到。