2011-04-26 16 views
7

Ésta es una continuación de una pregunta que hice ayer:procedimiento almacenado da diferente conjunto de resultados que tsql, sólo en algunos servidores

Have you ever had SQL Server 2008 return a different result set than SQL Server 2000?

en el que originalmente se pensó que el procedimiento almacenado estaba dando resultados diferentes personas en SQL2000 versus sql2008, pero reduje un poco el problema y eliminé bastante código para convertirlo en un problema simple/reproducible. El resumen es, una pieza de TSQL cuando se ejecuta como un proc devuelve una respuesta diferente que el mismo bit de código que se ejecuta como tan solo TSQL, pero sólo en mi servidor clientes, no en cualquiera de mis servidores de prueba.

Cuando ejecuto este TSQL:

DECLARE @PropertyID int 
DECLARE @PortfolioID int 
DECLARE @StartDate datetime 
DECLARE @EndDate datetime 
DECLARE @AcctMethod tinyint 

SET @PropertyId=3555 
--SET @PortfolioId = null 
SET @StartDate= '3/1/2010' 
SET @EndDate='2/28/2011' 
SET @AcctMethod=1 

DECLARE @ErrorMsg varchar(70) 
DECLARE @ExclAcct tinyint 

SET NOCOUNT ON 
CREATE TABLE #IncomeStatement (
    PropertyID  int, 
    GLAccountID  int, 
    SubTotalAccountID int, 
    Debits   money, 
    Credits   money, 
    YTDDebits  money, 
    YTDCredits  money, 
    PZDebits  money, 
    PZCredits  money, 
    AccountType  tinyint 
) 

--Initialize Temporary Table 
INSERT INTO #IncomeStatement(PropertyID, GLAccountID, SubTotalAccountID, AccountType, Debits, Credits, YTDDebits, YTDCredits, PZDebits, PZCredits) 
SELECT PropertyID, ID, SubTotalAccountID, AccountType, 0, 0, 0, 0, 0, 0 
FROM ChartOfAccounts 
WHERE (PropertyID = @PropertyID OR @PropertyID Is Null) 
    AND (@PortfolioID is null OR PropertyID in (select PropertyID from PortfolioProperty where [email protected])) 
    AND (Category > 3 or CashFlowCode <> 0) 

--Period Activity 
IF @AcctMethod = 1 
    SET @ExclAcct = 0 
ELSE 
    SET @ExclAcct = 1 

UPDATE Bal 
SET 
    Debits = Debits + D.TotDebit, 
    Credits = Credits + D.TotCredit 
FROM #IncomeStatement Bal 
    INNER JOIN (SELECT GLAccountID, Sum(Debit) AS TotDebit, Sum(Credit) AS TotCredit 
      FROM GLTransaction GT 
      WHERE (GT.PropertyID = @PropertyID OR @PropertyID Is Null) 
       AND AccountingMethod <> @ExclAcct 
       AND Posted = 1 
       AND TranDate >= @StartDate 
       AND TranDate <= @EndDate 
      GROUP BY GLAccountID) AS D 
     ON BAL.GLAccountID = D.GLAccountID 

select * from #IncomeStatement where GLAccountID=11153 
drop table #IncomeStatement 

me sale una cantidad de débito de $ 124.27, sin embargo, cuando se enciende el código anterior en un procedimiento almacenado de esta manera:

CREATE Procedure [dbo].[sp_test] 
    @PropertyID int = Null, 
    @PortfolioID int = Null, 
    @StartDate datetime = Null, 
    @EndDate datetime = Null, 
    @AcctMethod tinyint = 1 

AS 


DECLARE @ErrorMsg varchar(70) 
DECLARE @ExclAcct tinyint 

SET NOCOUNT ON 
CREATE TABLE #IncomeStatement (
    PropertyID  int, 
    GLAccountID  int, 
    SubTotalAccountID int, 
    Debits   money, 
    Credits   money, 
    YTDDebits  money, 
    YTDCredits  money, 
    PZDebits  money, 
    PZCredits  money, 
    AccountType  tinyint 
) 

--Initialize Temporary Table 
INSERT INTO #IncomeStatement(PropertyID, GLAccountID, SubTotalAccountID, AccountType, Debits, Credits, YTDDebits, YTDCredits, PZDebits, PZCredits) 
SELECT PropertyID, ID, SubTotalAccountID, AccountType, 0, 0, 0, 0, 0, 0 
FROM ChartOfAccounts 
WHERE (PropertyID = @PropertyID OR @PropertyID Is Null) 
    AND (@PortfolioID is null OR PropertyID in (select PropertyID from PortfolioProperty where [email protected])) 
    AND (Category > 3 or CashFlowCode <> 0) 

--Period Activity 
IF @AcctMethod = 1 
    SET @ExclAcct = 0 
ELSE 
    SET @ExclAcct = 1 

UPDATE Bal 
SET 
    Debits = Debits + D.TotDebit, 
    Credits = Credits + D.TotCredit 
FROM #IncomeStatement Bal 
    INNER JOIN (SELECT GLAccountID, Sum(Debit) AS TotDebit, Sum(Credit) AS TotCredit 
      FROM GLTransaction GT 
      WHERE (GT.PropertyID = @PropertyID OR @PropertyID Is Null) 
       AND AccountingMethod <> @ExclAcct 
       AND Posted = 1 
       AND TranDate >= @StartDate 
       AND TranDate <= @EndDate 
      GROUP BY GLAccountID) AS D 
     ON BAL.GLAccountID = D.GLAccountID 

select * from #IncomeStatement where GLAccountID=11153 
drop table #IncomeStatement 

y luego ejecutar loke que esto:

EXEC sp_test @PropertyID=3555, @StartDate='03/01/2010', @EndDate='02/28/2011' 

me sale una cantidad de débito de $ 248.54, que es exactamente el doble de lo que debería ser.

estoy realmente perplejo. Lo más extraño es que si hago una copia de seguridad de esta base de datos y luego la copio en mi servidor win2003 ejecutando sql2000 o en mi servidor win2008 que ejecuta SQL2008R2, funciona correctamente en ambos casos. Entonces, parece es una configuración de servidor o base de datos que está causando el problema, pero se han quedado sin cosas para verificar, con la esperanza de que un nuevo par de ojos pueda señalar algo obvio que me falta.

+0

Wow, comportamiento extraño. – alex

+0

Eso es realmente extraño. ¿Puede decir si está comenzando con el mismo número de registros en #IncomeStatement en ambos casos? Además, ¿ha intentado utilizar una variable de tabla en lugar de una tabla temporal? Tal vez hay una configuración en el tempdb en el servidor de los clientes que está causando cierta rareza aquí. – rsbarro

+0

¿Ha comprobado si SET ANSI_NULLS hace la diferencia? http://msdn.microsoft.com/en-us/library/ms188048.aspx –

Respuesta

7

OK, aquí está mi solución - es absolutamente no no explica el problema original, pero esto es lo que hice:

Cada vez que tengo un "descubrimiento de parámetros" problema de rendimiento, con el fin de resolver que yo declarar variables 'locales' para todos los parámetros, asignar los parámetros de las variables, y luego usar sólo las variables locales en el resto del proc, así:

ALTER Procedure [dbo].[rptDateIncomeStatementPlusCash] 
     @PropertyID int = Null, 
     @PortfolioID int = Null, 
     @StartDate datetime = Null, 
     @EndDate datetime = Null, 
     @AcctMethod tinyint = 1 
    AS 
     DECLARE @xPropertyID int 
     DECLARE @xPortfolioID int 
     DECLARE @xStartDate datetime 
     DECLARE @xEndDate datetime 
     DECLARE @xAcctMethod tinyint 

     SET @xPropertyID= @PropertyId 
     SET @xPortfolioId = @PortfolioId 
     SET @xStartDate = @StartDate 
     SET @xEndDate = @EndDate 
     SET @xAcctMethod = @AcctMethod 

la similitud es que cuando el parámetro olfateo es un problema , puede ejecutar un proceso almacenado a través del estudio MGMT y obtener un mejor rendimiento que ejecutarlo como un SQL, y los cambios (como los de arriba), usu aliado arreglarlo.

En mi caso, yo estaba viendo una diferencia entre TSQL recta en comparación con la ejecución de la proc (aunque no estaba relacionada con el rendimiento), que le dio una oportunidad - y presto funcionó; Desearía tener una mejor explicación, porque, sinceramente, me da miedo pensar que, en ocasiones, el servidor SQL dará resultados inconsistentes cuando se ejecuta un código casi idéntico.

encontré this bulletin from MS sobre un problema similar pero diferente, que por lo menos confirma que bajo las circunstancias adecuadas, el servidor SQL le puede dar malas respuestas, y this related bug report con esta frase clave:

Descripción: Dos cada sesión hace muchas llamadas a un procedimiento P con cambiando los valores de los parámetros. El procedimiento P ejecuta una consulta contra datos estáticos, a veces con la opción (RECOMPILE) y, a veces sin.

Ocasionalmente P da resultados incorrectos (para la reproducción a continuación, esto normalmente ocurre aproximadamente 1/2% - 1% del tiempo). Cuando los resultados de P son incorrectos, P devuelve 0 o el doble del número esperado de filas.

Alguien ayer dejó un comentario sobre el descubrimiento de parámetros como una posibilidad, pero por alguna razón que elimina sus comentarios (o respuesta) por lo que no puede dar crédito a ellos por la punta.

+0

Tenemos un procedimiento que genera posibles coincidencias para un algoritmo de lotería utilizado por una empresa en un país donde se requiere que tengan un rendimiento matemático de, digamos, 50% de regreso a todos los clientes para juegos de lotería. Un problema que tuvimos con la consulta fue que si ejecutamos el proceso almacenado directamente, no obtendríamos resultados por debajo del 80%, pero si resaltáramos el bloque en SSMS y lo ejecutaramos, obtendríamos una distribución de valores mucho mejor. No estábamos cambiando los valores de los parámetros, pero hacer lo que estaba aquí -crear nuevos valores y asignar los valores- funcionó a la perfección. ** ¡Gracias! ** –

1

Here is the execution plan, for those interested - could figure out how do this as a comment

+0

Esto es en respuesta al comentario anterior que busca el plan de ejecución; no se pudo agregar como comentario. –

+1

Me pregunto si aciertan a un error con paralelismo: con 2 hilos simultáneos procesan los mismos datos o algo así. Parece que hubo [algunos errores de paralelismo] (http://support.microsoft.com/kb/888799) corregidos en SQL Server 2000 SP4, pero no pude ver uno que se viera claramente relacionado. –

Cuestiones relacionadas