简体   繁体   中英

Speeding up SQL Server stored procedure

I really need help speeding up the following query in SQL Server. Right now I have it as a view but I don't care if it's a view or a function, I just need it to return a recordset to MS Access interface. The query takes 11 seconds to execute but with all of the cycles it goes through I need it down to 3 or less seconds. I've tried to index the view I have now but unfortunately I can't use the AVG function or use a HAVING clause if I am going to index anything.

SELECT tblFi.fldFN
    ,tblFc.fldFC
    ,tblFc.fldCity
    ,tblFc.fldState
    ,tblFi.fldIN
    ,tblAPL.fldPK
    ,tblAPL.fldCI
    ,AVG(tblAPD.fldND) AS fldND
FROM tblAPD
INNER JOIN tblAPL ON tblAPD.fldLK = tblAPL.fldLID
INNER JOIN tblUA ON tblAPD.fldUAK = tblUA.fldUAID
INNER JOIN tblUL ON tblUA.fldULK = tblUL.fldULID
INNER JOIN tblFi ON tblUL.fldFK = tblFi.fldFID
INNER JOIN tblFc ON tblFi.fldFAC = tblFc.fldFacID
GROUP BY tblFi.fldFN
    ,tblFc.fldFac
    ,tblFc.fldCity
    ,tblFc.fldState
    ,tblFi.fldIN
    ,tblAPL.fldPK
    ,tblAPL.fldCI
    ,tblAPL.fldPG
    ,tblAPD.fldIG
HAVING (tblAPL.fldCI <> 0) 
AND (AVG(tblAPD.fldND) IS NOT NULL) 
AND (tblAPL.fldPG = 1) 
AND (tblAPD.fldIG = 0)

The following are the tables (I only included pseudo names for the columns referenced in the query and then fld1, fld2, fld3 for those that are irrelevant)...

tblAPL -- 4.5 million rows, clustered Index on fldLID

fldLID... INT
fld1... FLOAT
fldCI... FLOAT
fldPK... BIGINT
fldPG... TINYINT
fld2... TINYINT
fld3... TINYINT
fld4... NVARCHAR(15)
fld5... DATETIME
fld6... TINYINT
fld7... TINYINT

tblAPD -- 12 million rows, clustered Index on fldDID

fldND... FLOAT
fldLK... INT
fldUAK... INT
fldIG... TINYINT
fld1... SMALLINT
fld2... SMALLINT
fld3... SMALLINT
fld4... NVARCHAR(20)
fld5... TINYINT
fldDID... INT

tblUA -- 850,000 rows, clustered Index on fldUAID

fldULK... INT
fldUAID... INT
fld1... NVARCHAR(10)
fld2... INT
fld3... NVARCHAR(15)
fld4... INT
fld5... TINYINT
fld6... NVARCHAR(10)
fld7... INT
fld8... TINYINT
fld9...TINYINT
fld10...TINYINT

tblUL -- 200,000 rows, clustered Index on fldULID

fldULID... INT
fldFK... INT
fld1... INT
fld2... INT
fld3... INT
fld4... NVARCHAR(15)
fld5... DATETIME
fld6... DATETIME

You can start by adding SET NOCOUNT ON; This should speed it up quite a bit.

Have you tried changing your HAVING clause into a simple WHERE clause? The only part you really can't move to a WHERE clause is the second line (the one with the AVG statement), right? This might speed it up since HAVING criteria are not evaluated until the entire resultset is generated.

SELECT tblFi.fldFN
    ,tblFc.fldFC
    ,tblFc.fldCity
    ,tblFc.fldState
    ,tblFi.fldIN
    ,tblAPL.fldPK
    ,tblAPL.fldCI
    ,AVG(tblAPD.fldND) AS fldND
FROM tblAPD (NOLOCK)
INNER JOIN tblAPL (NOLOCK) ON tblAPD.fldLK = tblAPL.fldLID
INNER JOIN tblUA (NOLOCK) ON tblAPD.fldUAK = tblUA.fldUAID
INNER JOIN tblUL (NOLOCK) ON tblUA.fldULK = tblUL.fldULID
INNER JOIN tblFi (NOLOCK) ON tblUL.fldFK = tblFi.fldFID
INNER JOIN tblFc (NOLOCK) ON tblFi.fldFAC = tblFc.fldFacID
GROUP BY tblFi.fldFN
    ,tblFc.fldFac
    ,tblFc.fldCity
    ,tblFc.fldState
    ,tblFi.fldIN
    ,tblAPL.fldPK
    ,tblAPL.fldCI
    ,tblAPL.fldPG
    ,tblAPD.fldIG
WHERE (tblAPL.fldCI <> 0) 
AND (tblAPL.fldCI = 1) 
AND (tblAPD.fldIG = 0)
HAVING (AVG(tblAPD.fldND) IS NOT NULL)

Make an NON CLUSTERED INDEX over(fldCI) and (fldIG) Hopefully you have an index for all foreign keys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM