kolmapäev, 22. juuli 2009

Muutujat kasutava SQL päringu kiirendamine OPTION(RECOMPILE) kasutamisega

Üks päring millega päev otsa vaeva nägin. Tehtud täitsa mõistlik SP, mille sees üks päring

DECLARE @apref VARCHAR(1)
SET @apref='C'

SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL

mis töötab aga jube aegalselt

kui päring muuta lihtsalt ilma muutuja kasutamiseta päringuks

SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = 'C'+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL

on asi kiire
Probleem selles, et SQL SERVER-i optimisaator teeb tervele SP-le optimiseerimise ja
SELECT lause koha peal ta ei tea mis on @apref väärtus ja üritab seda pimesi arvata

Üks võimalus on teha dünaamiline SQL aga parem on kasutada OPTION(RECOMPILE) SELECT lause juures

SELECT ACCOUNT.ID FROM DBO.ACCOUNT WHERE NOT EXISTS
( SELECT fd.[inv_no] FROM [dbo].[Cust_ Ledger Entry] fd WHERE
fd.[inv_no] = @apref+CAST(ACCOUNT.ID AS VARCHAR(30)) ) AND ACCOUNT.
W_SENT IS NOT NULL OPTION(RECOMPILE)

sel juhul optimisaator vaatab muutja @apref väärtust päringu tegemise hetkel ja päring läheb kiireks

Asja lahendamise juures olid abiks SQLMONSTERi inimesed
http://www.sqlmonster.com/Uwe/Forum.aspx/sql-server-performance/331/Variable-in-SELECT-expression-causes-query-degradation