2

以下は私のストアドプロシージャです。

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

SELECTステートメントに似たストアド プロシージャに、さらに 7 つのステートメント (簡潔にするために質問には含まれていません) があり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 秒かかります。このストアド プロシージャを改善するにはどうすればよいですか? ストアド プロシージャに関する知識はほとんどありません。

4

3 に答える 3

0

まあ、一時テーブルを取り除くことによってのみ最適化できます。あなたのアプローチは、それがストアドプロシージャであるためではなく(したがって、SP部分はまったく無関係です)、線形実行を強制し、クエリオプティマイザーが前進するより良い日を見つけるのを難しくする多くの一時テーブルを実行するためです.

この特定のケースでは、データベースの設計が恐ろしく悪い可能性があり (なぜ #result 1 から #result 8 を開始するのか)、ストアド プロシージャごとに大量の「一時テーブルへのコピー」がある可能性があります。

SQL のクエリ最適化は「ステートメントごと」に機能し、ステートメント間で実行が並列化されることはありません。そのため、ここでは一時テーブルの処理が実際に邪魔になります。一時テーブルを取り除きます。

于 2013-02-04T07:13:59.370 に答える
0

直接使用しないでください SELECT * INTO #temp INSTEAD 常に #temp テーブルを作成してから INSERT INTO #temp を使用すると、クエリの実行時間が 70% 短縮されます

正確な構造で #temp テーブルを作成するのはイライラするかもしれませんが、そのためのショートカットを次に示します。これは一度実行されます

呼び出し元のクエリから SELECT * INTO tableName を使用して dbo.tableName を作成すると、sp_help TableName によって構造が提供されます。次に、ストア プロシージャで #temp テーブルを作成します。

実行に45分かかっていたクライアントのクエリを最適化し、このロジックに置き換えただけでうまくいきました!!! 今では5分かかります!!

于 2013-02-04T07:35:26.770 に答える
0

where節、IsActiveAccountIDおよびの列で非クラスター化インデックスを生成しますAbused

于 2013-02-04T07:12:38.723 に答える