Utilizzare i parametri di output di una stored procedure in certe situazioni può essere molto performante rispetto all'uso del recordset nel recuperare dati da SQL Server tramite ADO. Questa tecnica può esserci di aiuto quando dobbiamo recuperare una singola riga da una tabella, come nel caso delle pagine web di dettaglio che riportano informazioni su uno specifico prodotto. Qui l'istruzione SQL Â da inviare al server è simile a questa:
La SELECT precedente recupera sempre una singola riga Prodotti
Un esempio pratico
Per quantificare l'efficienza di un metodo rispetto all'altro ho preparato due stored procedures e due scripts ASP in cui provare gli approcci. Gli esempi si basano sul database Northwind di SQL Server 2000. Entrambe le stored procedure ritornano un singolo record formato da quattro campi presenti su tre tabelle differenti: Products, Categories e Suppliers.
La prima procedura InfoProdotto_1 Â usa l'istruzione SELECT per recuperare il record e quindi usiamo l'oggetto Recordset di ADO per l'output dei risultati sulla pagina ASP.
CREATE PROCEDURE InfoProdotto_1
@ProdottoID int
AS
SELECT p.ProductName, c.CategoryName, s.CompanyName, p.UnitPrice
FROM Products p INNER JOIN Suppliers s ON p.SupplierID = s.SupplierID
INNER JOIN Categories c ON p.CategoryID = c.CategoryID
WHERE p.ProductID=@ProdottoID
GO
La seconda invece, InfoProdotto_2 , usa i parametri di OUTPUT della procedura per recuperare i campi del record e quindi usiamo l'oggetto Command
--Seconda procedura: recupero i valori dai parametri di output della sp
CREATE PROCEDURE InfoProdotto_2
@ProdottoID int,
@NomeProdotto nvarchar(40) OUTPUT,
@NomeAzienda nvarchar(40) OUTPUT,
@NomeCategoria nvarchar(15) OUTPUT,
@PrezzoUnitario money OUTPUT
AS
SELECT
@NomeProdotto=p.ProductName,
@NomeCategoria=c.CategoryName,
@NomeAzienda=s.CompanyName,
@PrezzoUnitario=p.UnitPrice
FROM Products p INNER JOIN Suppliers s ON p.SupplierID = s.SupplierID
INNER JOIN Categories c ON p.CategoryID = c.CategoryID
WHERE p.ProductID=@ProdottoID
GO
Per testare le performance ho creato due scripts ASP che utilizzano ADO per fare chiamate ripetute alle stored procedures appena create.
Come si può vedere dal codice sottostante, ogni script chiama in modo continuato per 15 secondi la procedura opportuna incrementando ad ogni chiamata un contatore che alla fine costituirà il parametro di paragone tra i due metodi.
Il primo script ASP dal nome Prod1.asp InfoProdotto_1
lCount=0
do while DateDiff("s",StartTime,time)<15
lCount=lCount+1
 Set rs = cmd.ExecuteÂ
loop
Il secondo script ASP dal nome Prod2.asp invece InfoProdotto_2
lCount=0
do while DateDiff("s",StartTime,time)<15
lCount=lCount+1
cmd.ExecuteÂ
loop
Per entrambi gli script l'output dei valori viene stampato una sola volta alla fine del ciclo di chiamate per non "sporcare" lo stress test. Nel primo script i valori sono contenuti nell' oggetto Recordset Parameters Command
Il codice di Prod1.asp
Il codice di Prod2.asp
Uno sguardo ai risultati del test
Le prove che ho effettuato sul mio PC portatile (Windows 2000 Advanced Server, SQL Server 2000 Enterprise Edition, 256 MB RAM, PIII 933) non possono essere di riferimento rispetto ad un ambiente di produzione ma sono sicuramente utili per discutere i risultati ottenuti. Lo script Prod1.asp ha recuperato le informazioni sul prodotto 2543 volte contro le 15345 volte dello script Prod2.asp nello stesso arco di tempo di 15 secondi. Strabiliante, il secondo script ha mostrato un incremento superiore al 600%!
Il motivo di questo gap di prestazioni non è attribuibile a SQL Server perché la velocità di esecuzione e le prestazioni delle due stored procedures sono praticamente identiche ma tuttalpiù ad ADO perchè il recupero delle informazioni attraverso il Recordset è molto più lento e meno performante rispetto alla stessa cosa fatta con l'interrogazione della collection Parameters dell'oggetto Command.
Quindi nel caso ci dovessimo trovare davanti ad una pagina web che ha molti accessi concorrenti potrebbe essere utile, se possibile, usare la collection di parametri di Command per recuperare i valori dal database anziché il classico Recordset e l'applicazione sarebbe certamente più veloce!