提取WHERE子句以加速查询

时间:2016-01-07 15:30:08

标签: sql sql-server

下面“第1节”中显示的查询需要2.5小时才能完成。我的任务是加快速度,我对我所做的改变是否合法(即不会改变结果)有疑问。我的修改后的代码在< 30分钟非常感谢。

1)ORIGINAL QUERY

SELECT i.FundCD
    ,i.MaxDate
    ,v1.InfoCodeName AS ParentInfoCodeName
    ,v2.InfoCodeName
    ,FieldValue
    ,i.NotFormattedDecimalValue AS FieldValue
    ,i.AsOfDate
INTO #tmp_hfri
FROM pmw.dbo.vInfoCodeWithHierarchy v1
INNER JOIN pmw.dbo.vInfoCodeWithHierarchy v2 ON v1.CodeNode = v2.ParentCodeNode
INNER JOIN pmw.dbo.vFundInfo i ON v2.InfoCodeID = i.CodeID
WHERE v1.InfoCodeID IN (
        692857
        ,693600
        )

2)我看到最后一行中的WHERE子句要求v1.InfoCodeID中存在两个值中的一个。 v1所以我认为我可以使用v1.InfoCodeID的值在v1中预先选择行,并在查询中使用它而不是v1(1049行)中的所有行,以加快完整查询。

3)我做了:

SELECT *
   INTO #t1
   FROM pmw.dbo.vInfoCodeWithHierarchy v1 
   WHERE v1.InfoCodeID in (692857,693600)

4)然后运行此查询。它需要< 30分钟

SELECT i.FundCD
    ,i.MaxDate
    ,v1.InfoCodeName AS ParentInfoCodeName
    --convert(float,replace(i.FieldValue,'%',''))*0.01 as FieldValue,
    ,v2.InfoCodeName
    ,i.NotFormattedDecimalValue AS FieldValue
    ,i.AsOfDate
INTO #tmp_hfri
FROM #t1 v1
INNER JOIN #t1 v2 ON v1.CodeNode = v2.ParentCodeNode
INNER JOIN pmw.dbo.vFundInfo i ON v2.InfoCodeID = i.CodeID
WHERE v1.InfoCodeID IN (
        692857
        ,693600
        )

1 个答案:

答案 0 :(得分:1)

是的,这是一种合法的技术,但在这种情况下,您可能会排除行。在第一个查询中,您只限制v1WHERE v1.InfoCodeID IN (692857,693600)的结果,但在第二个查询中,因为您引用临时表代替v2,您也限制了结果在这里,您的第二个查询相当于:

SELECT  i.FundCD,
        i.MaxDate,
        v1.InfoCodeName AS ParentInfoCodeName,
        --convert(float,replace(i.FieldValue,'%',''))*0.01 as FieldValue,
        v2.InfoCodeName,
        i.NotFormattedDecimalValue AS FieldValue,
        i.AsOfDate
INTO    #tmp_hfri
FROM    pmw.dbo.vInfoCodeWithHierarchy v1
        INNER JOIN pmw.dbo.vInfoCodeWithHierarchy v2 
            ON v1.CodeNode = v2.ParentCodeNode
        INNER JOIN pmw.dbo.vFundInfo i 
            ON v2.InfoCodeID = i.CodeID
WHERE   v1.InfoCodeID IN (692857 ,693600)
AND     v2.InfoCodeID IN (692857 ,693600); -- ADDITIONAL FILTER 

您看到性能差异的原因归结为中间物化。通过执行较小的部分并将结果存储在临时表中来强制中间实现是一种合法的技术。 Adam Machanic有written a pretty good article on it,而且有。{3}} 还为{s}服务器打开connect item以添加查询提示,以允许用户强制结果集的中间实现,以避免需要临时表。

您可能仍然发现使用临时表更快,但您仍然需要引用v2的视图:

SELECT CodeNode, InfoCodeName -- ONLY PUT FIELDS YOU NEED INTO THE TEMP TABLE
INTO #t1
FROM pmw.dbo.vInfoCodeWithHierarchy v1 
WHERE v1.InfoCodeID in (692857,693600)

SELECT  i.FundCD,
        i.MaxDate,
        v1.InfoCodeName AS ParentInfoCodeName,
        --convert(float,replace(i.FieldValue,'%',''))*0.01 as FieldValue,
        v2.InfoCodeName,
        i.NotFormattedDecimalValue AS FieldValue,
        i.AsOfDate
INTO    #tmp_hfri
FROM    #t1 v1
        INNER JOIN pmw.dbo.vInfoCodeWithHierarchy v2 
            ON v1.CodeNode = v2.ParentCodeNode
        INNER JOIN pmw.dbo.vFundInfo i 
            ON v2.InfoCodeID = i.CodeID;

如果您仍然遇到性能问题(即使查询减少到30分钟,我猜你也是),那么你需要查看执行计划,找出瓶颈并可能创建一些索引。