2017-06-01 181 views
0

在此查詢中,我在下面的查詢中調用函數「fnGetPoolWinner」2-3次, ,我認爲這會減慢其性能或多個case語句是原因。如何優化查詢花費太多時間

00:01:39左右需要時間。

我嘗試過在表中創建indxes和創建公用表表達式,然後使用該查詢,但還沒有找到任何解決方案來減少它的時間。

DECLARE @TournamentId INT = 1 

DECLARE @TournamentName AS NVARCHAR(MAX) 

SELECT @TournamentName = TournamentName FROM Tournaments WHERE TournamentId = @TournamentId 


    SELECT 
    (SELECT CustomerIds FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId, 
    (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 1 
     WHEN SET_1.GAMES= 31 
     THEN 2 
     WHEN SET_1.GAMES= 15 
     THEN 3 
     ELSE 0 
    END))) AS [AccountNumber], 
    @TournamentName AS TournamentName, 
    (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+'' 
     WHEN SET_1.GAMES= 31 
     THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+'' 
     WHEN SET_1.GAMES= 15 
     THEN 'GENERAL POOL SWEET 16 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+'' 
     ELSE '' 
    END) AS [PoolName], 
    (SELECT BracketNames FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId, 
    (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 1 
     WHEN SET_1.GAMES= 31 
     THEN 2 
     WHEN SET_1.GAMES= 15 
     THEN 3 
     ELSE 0 
    END))) AS GroupEntries, 
    'Public' AS Access, 
    COUNT(SET_1.BracketId) AS Members, 
    COUNT(SET_1.BracketId)*SET_1.BracketBettingAmount AS CurrentPoolPrize, 
    (SELECT WinnerNames FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId, 
    (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 1 
     WHEN SET_1.GAMES= 31 
     THEN 2 
     WHEN SET_1.GAMES= 15 
     THEN 3 
     ELSE 0 
    END))) AS WinnersName, 
    (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 1 
     WHEN SET_1.GAMES= 31 
     THEN 2 
     WHEN SET_1.GAMES= 15 
     THEN 3 
     ELSE 0 
    END) AS RoundId, 
    SET_1.BracketBettingAmount AS BettingAmount 
    FROM 
     (SELECT BR.BracketId, 
      BracketBettingAmount, 
      (SELECT COUNT(1) FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId) AS GAMES 
     FROM Brackets AS BR WHERE BR.BracketTournamentId = @TournamentId AND BR.IsDeleted = 0) SET_1 WHERE SET_1.GAMES > 0 
    GROUP BY SET_1.BracketBettingAmount, SET_1.GAMES HAVING SET_1.BracketBettingAmount IN (1,5,10,25) 
+0

檢查查詢執行計劃,它可以如建議您添加索引以獲得更好的性能。 – niksofteng

+0

有時我可以減少至少300%的查詢執行時間,刪除別名表達式,嵌套函數,直接在子查詢中輸入where子句等 – PiLHA

+0

@niksofteng,謝謝你的建議。我已經檢查過SSMS中的查詢執行計劃。我還在相關表格中添加了索引。但不幸的是沒有得到任何結果。 – jeet

回答

0

試試這個,沒有測試

DECLARE @TournamentId INT = 1 

    with SET_1 as (

     SELECT BR.BracketId, BracketBettingAmount as BettingAmount, W.GAMES, TN.TournamentName, 
      case W.GAMES 
      WHEN 63 THEN 1 
      WHEN 31 THEN 2 
      WHEN 15 THEN 3 
      ELSE 0 END as IDGAME, 

      CASE W.GAMES 
      WHEN 63 THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR) 
      WHEN 31 THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR) 
      WHEN 15 THEN 'GENERAL POOL SWEET 16 $' +CAST(CAST(BracketBettingAmount AS INT) AS NVARCHAR) 
      ELSE '' END AS PoolName, 

      TN.TournamentId 

      FROM Brackets AS BR 
      cross apply 
      (
       SELECT COUNT(*) GAMES FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId 
      ) W 

      inner join Tournaments TN on BR.BracketTournamentId=TN.TournamentId 

      WHERE BR.IsDeleted = 0 and BracketBettingAmount IN (1,5,10,25) and W.GAMES>0 and TN.TournamentId = @TournamentId 


    ), 

    NbBracketId as (select NbBracketId, count(*) Nb from SET_1 group by NbBracketId) 


    SELECT 
    Y.CustomerIds AccountNumber, X.TournamentName, X.PoolName, Y.BracketNames AS GroupEntries, 'Public' AS Access, 
    Z.NB AS Members, Z.NB*X.BettingAmount AS CurrentPoolPrize, Y.WinnerNames, X.IDGAME AS RoundId, X.BettingAmount 
    FROM SET_1 X 
    outer apply DBO.fnGetPoolWinner(SET_1.BracketBettingAmount, SET_1.TournamentId, SET_1.IDGAME) as Y 
    inner join NbBracketId Z on X.BracketId=Z.BracketId 
0

DBO.fnGetPoolWinner可租期,提高自身。

嘗試這種方法,在SSMS

DECLARE @TournamentId INT = 1 
DECLARE @TournamentName AS NVARCHAR(MAX) 
SELECT @TournamentName = TournamentName FROM Tournaments WHERE TournamentId = @TournamentId 
select @TournamentName TournamentName, 
CustomerIds AS [AccountNumber] 
,(CASE 
     WHEN SET_1.GAMES= 63 
     THEN 'GENERAL POOL ROUND OF 64 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+'' 
     WHEN SET_1.GAMES= 31 
     THEN 'GENERAL POOL ROUND OF 32 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+'' 
     WHEN SET_1.GAMES= 15 
     THEN 'GENERAL POOL SWEET 16 $'+CAST(CAST(SET_1.BracketBettingAmount AS INT) AS NVARCHAR)+'' 
     ELSE '' 
    END) AS [PoolName] 
    ,ca.BracketNames as GroupEntries 
    'Public' AS Access, 
    COUNT(SET_1.BracketId) AS Members, 
    COUNT(SET_1.BracketId)*SET_1.BracketBettingAmount AS CurrentPoolPrize 
    ,WinnerNames as WinnersName 
    , (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 1 
     WHEN SET_1.GAMES= 31 
     THEN 2 
     WHEN SET_1.GAMES= 15 
     THEN 3 
     ELSE 0 
    END) AS RoundId, 
    SET_1.BracketBettingAmount AS BettingAmount 
FROM 
     (SELECT BR.BracketId, 
      BracketBettingAmount, 
      (SELECT COUNT(1) FROM BracketPredictions AS BP WHERE BP.BracketPredictionBracketId =BR.BracketId) AS GAMES 
     FROM Brackets AS BR WHERE BR.BracketTournamentId = @TournamentId AND BR.IsDeleted = 0) SET_1 
     WHERE SET_1.GAMES > 0 
    GROUP BY SET_1.BracketBettingAmount, SET_1.GAMES 
    HAVING SET_1.BracketBettingAmount IN (1,5,10,25) 

    cross apply(SELECT CustomerIds,BracketNames,WinnerNames 
    FROM DBO.fnGetPoolWinner(SET_1.BracketBettingAmount,@TournamentId, 
    (CASE 
     WHEN SET_1.GAMES= 63 
     THEN 1 
     WHEN SET_1.GAMES= 31 
     THEN 2 
     WHEN SET_1.GAMES= 15 
     THEN 3 
     ELSE 0 
    END)))ca