0

この複雑なクエリの最適化または書き直しについてサポートが必要です。クエリは 50 行のテスト データでうまく機能しましたが、実際のデータは 700,000 行を超え、クエリの実行には 5 分以上かかります。2 つのテーブルの主キーにインデックスがあります。エージ機能はコストの大部分を占めていると思いますが、これを取り除けば約 2 分半節約できます。任意の提案をいただければ幸いです。前もって感謝します。

WITH T AS (
        SELECT TOP 2000
          A.Residence_City, 
          CASE 
             WHEN A.Gender = 'M' then 'Male'
             WHEN A.Gender = 'F' then 'Female'
             WHEN A.Gender = 'U' then 'Unknown'
        END AS Gender,
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 18 and 24 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [0_3_18],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 18 and 24 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 1 then 1 else null end) as [1_3_18],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 18 and 24 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 2 then 1 else null end) as [2_3_18],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 18 and 24 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 3 then 1 else null end) as [3_3_18],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 18 and 24 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [Unknown_18],

count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 25 and 34 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [0_3_25],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 25 and 34 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 1 then 1 else null end) as [1_3_25],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 25 and 34 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 2 then 1 else null end) as [2_3_25],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 25 and 34 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 3 then 1 else null end) as [3_3_25],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 25 and 34 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [Unknown_25],

count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 35 and 49 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [0_3_35],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 35 and 49 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 1 then 1 else null end) as [1_3_35],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 35 and 49 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 2 then 1 else null end) as [2_3_35],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 35 and 49 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 3 then 1 else null end) as [3_3_35],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 35 and 49 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [Unknown_35],

count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 50 and 64 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [0_3_50],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 50 and 64 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 1 then 1 else null end) as [1_3_50],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 50 and 64 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 2 then 1 else null end) as [2_3_50],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 50 and 64 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 3 then 1 else null end) as [3_3_50],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 50 and 64 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [Unknown_50],

count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 65 and 120 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [0_3_65],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 65 and 120 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 1 then 1 else null end) as [1_3_65],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 65 and 120 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 2 then 1 else null end) as [2_3_65],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 65 and 120 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 3 then 1 else null end) as [3_3_65],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) between 65 and 120 and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [Unknown_65],

count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) = '' or voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() )is null and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [0_3_],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) = '' or voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() )is null and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 1 then 1 else null end) as [1_3_],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) = '' or voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() )is null and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 2 then 1 else null end) as [2_3_],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) = '' or voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() )is null and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 3 then 1 else null end) as [3_3_],
count(case when voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() ) = '' or voterData.dbo.ufn_GetAge ( convert(datetime,[Date_of_Birth]), GETDATE() )is null and voterData.dbo.GeneralVoting (V.[G10EC], V.[G08EC],V.[G06EC]) = 0 then 1 else null end) as [Unknown_]

from Personal as A INNER JOIN Voting_History V 
on A.Vuid = V.Vuid 
group by Residence_City, Gender with rollup
Order by Residence_City, Gender 
)
, temp1 as (
    SELECT  *,([3_3_18] + [3_3_25] + [3_3_35] + [3_3_50] + [3_3_65] + [3_3_]
              +[2_3_18] + [2_3_25] + [2_3_35] + [2_3_50] + [2_3_65] + [2_3_]
              +[1_3_18] + [1_3_25] + [1_3_35] + [1_3_50] + [1_3_65] + [1_3_]
              +[0_3_18] + [0_3_25] + [0_3_35] + [0_3_50] + [0_3_65] + [0_3_]
            +[Unknown_18]+ [Unknown_25]+ [Unknown_35] + [Unknown_50]+ [Unknown_65] + [Unknown_]) Total
FROM T
where NULLIF(Residence_City,'') IS NOT NULL
), temp2 as (
    SELECT * FROM temp1
UNION ALL
select 
'grand Total',
SUM([0_3_18])/2,SUM([1_3_18])/2,SUM([2_3_18])/2,SUM([3_3_18])/2,SUM([Unknown_18])/2,
SUM([0_3_25])/2,SUM([1_3_25])/2,SUM([2_3_25])/2,SUM([3_3_25])/2,SUM([Unknown_25])/2,
SUM([0_3_35])/2,SUM([1_3_35])/2,SUM([2_3_35])/2,SUM([3_3_35])/2,SUM([Unknown_35])/2,
SUM([0_3_50])/2,SUM([1_3_50])/2,SUM([2_3_50])/2,SUM([3_3_50])/2,SUM([Unknown_50])/2,
SUM([0_3_65])/2,SUM([1_3_65])/2,SUM([2_3_65])/2,SUM([3_3_65])/2,SUM([Unknown_65])/2,
SUM([0_3_])/2,SUM([1_3_])/2,SUM([2_3_])/2,SUM([3_3_])/2,SUM([Unknown_])/2,
sum(Total)/2

FROM temp1
)

SELECT Residence_City, Gender,
    [0_3_18]     as [0_3],  
    [1_3_18]     as [1_3], 
    [2_3_18]     as [2_3], 
    [3_3_18]     as [3_3], 
    [Unknown_18] as [Unknown],

    [0_3_25]     as [0_3],  
    [1_3_25]     as [1_3], 
    [2_3_25]     as [2_3],  
    [3_3_25]     as [3_3],  
    [Unknown_25] as [Unknown], 

    [0_3_35]     as [0_3],  
    [1_3_35]     as [1_3], 
    [2_3_35]     as [2_3], 
    [3_3_35]     as [3_3], 
    [Unknown_35] as [Unknown], 

    [0_3_35]     as [0_3],  
    [1_3_35]     as [1_3], 
    [2_3_35]     as [2_3], 
    [3_3_35]     as [3_3], 
    [Unknown_35] as [Unknown], 

    [0_3_35]     as [0_3],  
    [1_3_35]     as [1_3], 
    [2_3_35]     as [2_3], 
    [3_3_35]     as [3_3], 
    [Unknown_35] as [Unknown], 

    [0_3_35]     as [0_3],  
    [1_3_35]     as [1_3], 
    [2_3_35]     as [2_3], 
    [3_3_35]     as [3_3], 
    [Unknown_35] as [Unknown], 
    Total
   FROM temp2

これらは機能です

    ALTER FUNCTION [dbo].[GeneralVoting] ( @one varchar, @two varchar,@three varchar)
    RETURNS INT
    AS
    BEGIN

        DECLARE @vAge         INT

        SET @vAge = (CASE WHEN @one IS NOT NULL THEN 1 ELSE 0 END)
                        +(CASE WHEN @two IS NOT NULL THEN 1 ELSE 0 END)
                        +(CASE WHEN @three IS NOT NULL THEN 1 ELSE 0 END)
     RETURN @vAge
    END

    ALTER FUNCTION [dbo].[ufn_GetAge] ( @pDateOfBirth DATETIME, @pAsOfDate DATETIME )
    RETURNS INT
    AS
    BEGIN
        DECLARE @vAge         INT
        IF @pDateOfBirth >= @pAsOfDate
            RETURN 0

        SET @vAge = DATEDIFF(YY, @pDateOfBirth, @pAsOfDate)

        IF MONTH(@pDateOfBirth) > MONTH(@pAsOfDate) OR
          (MONTH(@pDateOfBirth) = MONTH(@pAsOfDate) AND
           DAY(@pDateOfBirth)   > DAY(@pAsOfDate))
            SET @vAge = @vAge - 1
      RETURN @vAge
    END
4

1 に答える 1

0

結合構造は妥当なようです。ロールアップが必要かどうかはわかりませんが、おそらくパフォーマンスには影響しません。

ユーザー定義関数がパフォーマンスに影響していると思われます。SQL Server は、ufn_GetAge() への複数回の呼び出しを最適化するほどスマートではないため、関数が何度も呼び出されます。代わりに、年齢をサブクエリに入れます。

(select *, voterData.dbo.ufn_GetAge( convert(datetime,[Date_of_Birth]), GETDATE() ) as age
 from VoterData
) age

この関数は非常に単純なので、インラインで置き換えてこの 1 回の呼び出しをなくすこともできます。

他の関数についても同じアプローチを取ることができます。

また、投票表と履歴表のサイズはどれくらいですか? 特に、都市と性別の組み合わせはいくつありますか? 上位 2000 件を事前に選択してから、さまざまなグループの計算を行うことで、クエリをより効率的にすることができる場合があります。ただし、サイズがわからないと、これが機能するかどうかを判断するのは困難です. また、本当に Residence_City, Gender で注文するつもりですか。. . または、他のフィールドのいずれかで並べ替えますか? そのまま、クエリはアルファベット順に最初のものを選択するだけです。

于 2012-05-12T16:27:42.840 に答える