【问题标题】:How to optimize stored procedures?如何优化存储过程?
【发布时间】:2013-02-04 07:05:12
【问题描述】:

以下是我的存储过程。

ALTER PROCEDURE [GetHomePageObjectPageWise]
       @PageIndex INT = 1
      ,@PageSize INT = 10
      ,@PageCount INT OUTPUT
      ,@AccountID INT
      ,@Interests Varchar(3000)
AS
BEGIN
      SET NOCOUNT ON;



      SELECT StoryID
      , AlbumID
      , StoryTitle
      , CAST(NULL as varchar) AS AlbumName
      , (SELECT URL FROM AlbumPictures WHERE (AlbumID = Stories.AlbumID) AND (AlbumCover = 'True')) AS AlbumCover
      , Votes
      , CAST(NULL as Int) AS PictureId
      , 'stories' AS tableName
      , (SELECT CASE WHEN EXISTS (
            SELECT NestedStories.StoryID FROM NestedStories WHERE (StoryID = Stories.StoryID) AND (AccountID=@AccountID)
        )
        THEN CAST(1 AS BIT)
        ELSE CAST(0 AS BIT) END) AS Flag
      , (SELECT UserName FROM UserAccounts WHERE Stories.AccountID=UserAccounts.AccountID) AS Username

INTO #Results1
FROM Stories WHERE FREETEXT(Stories.Tags,@Interests) AND AccountID <> @AccountID AND IsActive='True' AND Abused < 10

我在存储过程中还有 7 个 SELECT 语句(为简洁起见不包括在问题中),类似于 SELECT StoryID 语句,我 UNION ALL 喜欢这样

SELECT * INTO #Results9 FROM #Results1
UNION ALL
SELECT * FROM #Results2
UNION ALL
SELECT * FROM #Results3
UNION ALL
SELECT * FROM #Results4
UNION ALL
SELECT * FROM #Results5
UNION ALL
SELECT * FROM #Results6
UNION ALL
SELECT * FROM #Results7
UNION ALL
SELECT * FROM #Results8

SELECT ROW_NUMBER() OVER
            (
                  ORDER BY [tableName] DESC
            )AS RowNumber
            , * INTO #Results
            FROM #Results9


      DECLARE @RecordCount INT
      SELECT @RecordCount = COUNT(*) FROM #Results

      SET @PageCount = CEILING(CAST(@RecordCount AS DECIMAL(10, 2)) / CAST(@PageSize AS DECIMAL(10, 2)))


      SELECT * FROM #Results
      WHERE RowNumber BETWEEN(@PageIndex -1) * @PageSize + 1 AND(((@PageIndex -1) * @PageSize + 1) + @PageSize) - 1

      DROP TABLE #Results
      DROP TABLE #Results1
      DROP TABLE #Results2
      DROP TABLE #Results3
      DROP TABLE #Results4 
END

返回结果大约需要 6 秒。我该如何改进这个存储过程?我对存储过程知之甚少。

【问题讨论】:

    标签: sql sql-server sql-server-2008


    【解决方案1】:

    where 子句、IsActiveAccountIDAbused 中的列上建立非聚集索引。

    【讨论】:

      【解决方案2】:

      好吧,您只能通过摆脱临时表来优化它。您的方法很糟糕,不是因为它是一个存储过程(因此 SP 部分完全无关紧要),而是因为您做了很多临时表的东西,这些东西会强制线性执行并使查询优化器很难找到更好的日子继续前进.

      在这种特殊情况下,您的数据库设计可能非常糟糕(为什么要从 #result 1 到 #result 8 开始),然后您在每个存储过程中都有大量“复制到临时表”。

      SQL 中的查询优化“逐个语句”地工作,并且语句之间的执行永远不会并行 - 所以临时表的东西在这里真的很适合你。摆脱临时表。

      【讨论】:

      • 我怎样才能摆脱临时表?你能给我一个简短的例子吗?
      【解决方案3】:

      永远不要直接使用 SELECT * INTO #temp 反而 始终创建 #temp 表,然后 INSERT INTO #temp 这将减少 70% 的查询执行时间

      虽然创建具有精确结构的#temp 表可能会令人沮丧, 所以这里有一个捷径:这将执行一次

      使用调用查询中的 SELECT * INTO tableName 创建 dbo.tableName 然后 sp_help TableName 将提供结构。 然后在 Store Procedure 中创建 #temp 表。

      我已经为我们的一个客户优化了查询,它需要 45 分钟才能执行,只是用这个逻辑替换它工作! 现在需要 5 分钟!!

      【讨论】:

      • 你能给我举个例子吗?
      • 在您的情况下,#Results1 临时表是由 Select * INTO #Results1 创建的,而不是在开始时使用 create 命令创建表 #Results1。
      猜你喜欢
      • 2021-04-17
      • 2010-10-01
      • 1970-01-01
      • 2012-02-26
      • 2018-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多