Internal SQL Server Error

07/11/2006 - 15:03 por jcac | Informe spam
Hola lista tebgo un problema armando este query:

Select D.PROD_CodProd, Max(V.VALE_FecEmi),
(Select D1.DVAL_CostoPS From DetValesAlm D1 Inner Join Vales V1 On
D1.SUCR_Codigo = V1.SUCR_Codigo And D1.ALMA_Codigo = V1.ALMA_Codigo And
D1.TIPO_CodVale = V1.TIPO_CodVale And D1.VALE_NumVale = V1.VALE_NumVale
Where D.SUCR_Codigo = D1.SUCR_Codigo And D.ALMA_Codigo = D1.ALMA_Codigo
And D.TIPO_CodVale = D1.TIPO_CodVale And D.VALE_NumVale = D1.VALE_NumVale
And D.PROD_CodProd = D1.PROD_CodProd And Max(V.VALE_FecEmi) =
V1.VALE_FecEmi) As XX
From DetValesAlm D Inner Join Vales V On D.SUCR_Codigo = V.SUCR_Codigo And
D.ALMA_Codigo = V.ALMA_Codigo And D.TIPO_CodVale = V.TIPO_CodVale And
D.VALE_NumVale = V.VALE_NumVale
Where D.PROD_CodProd = '2130080001' And V.VALE_Estado = 'C' And
Month(V.VALE_FecEmi) = 9 And Year(V.VALE_FecEmi) = 2006
Group by D.PROD_CodProd


Cuando lo ejecute de esta manera no me pasa nada:

Select D.PROD_CodProd, Max(V.VALE_FecEmi)
From DetValesAlm D Inner Join Vales V On D.SUCR_Codigo = V.SUCR_Codigo And
D.ALMA_Codigo = V.ALMA_Codigo And D.TIPO_CodVale = V.TIPO_CodVale And
D.VALE_NumVale = V.VALE_NumVale
Where D.PROD_CodProd = '2130080001' And V.VALE_Estado = 'C' And
Month(V.VALE_FecEmi) = 9 And Year(V.VALE_FecEmi) = 2006
Group by D.PROD_CodProd

Ya que aqui consiguo el producto con su maxima fecha en un mes especifico,
sin embargo cuando deseo sacar su costo de ese producto lo hago haciendo el
primer query que le he puesto y me da el error del Asunto

Mi SQL Server es 2000 Standart con SP4 y corre bajo un Windows 2000 Server
SP4

Saludos y gracias por su tiempo

Preguntas similare

Leer las respuestas

#6 jcac
07/11/2006 - 17:40 | Informe spam
Hola Ele,

Si realice los cambios que me solicitaste pero luego me pedia que lo agrupe
por otros campos que no necesitaba.

Pensandolo lo que necesitaba lo busque de otra manera, ya que lo que queria
es el ultimo costo que tueviera dentro de 1 mes y esto lo consegui de esta
forma

Select Top 1 D.PROD_CodProd, D.DVAL_CostoPS, V.VALE_FecEmi
From Vales V Inner Join DetValesAlm D On V.SUCR_Codigo = D.SUCR_Codigo And
V.ALMA_Codigo = D.ALMA_Codigo And V.TIPO_TabVale = D.TIPO_TabVale And
V.TIPO_CodVale = D.TIPO_CodVale And V.VALE_NumVale = D.VALE_NumVale
Where V.VALE_Estado = 'C' And Month(V.VALE_FecEmi) = 9 And
Year(V.VALE_FecEmi) = 2006 And D.PROD_CodProd = '2130080001'
Order By V.VALE_FecEmi Desc

Gracias por el tiempo y la disposición de ayudar.

Saludos

"Ele" escribió en el mensaje
news:
Mostrar la cita
#7 jcac
07/11/2006 - 17:43 | Informe spam
Hola Alejandro

Si el query me diste funciona pero segun mis datos que hay cambios de costo
dentro del mismo mes, me vota distintos resultados, y solo queria el ultimo
resultado del mes, además que segun el plan de ejecucion se demora demasiado
cerca de 47 segun y realiza dos table scan, pensandolo de otra forma lo hice
asi:

Select Top 1 D.PROD_CodProd, D.DVAL_CostoPS, V.VALE_FecEmi
From Vales V Inner Join DetValesAlm D On V.SUCR_Codigo = D.SUCR_Codigo And
V.ALMA_Codigo = D.ALMA_Codigo And V.TIPO_TabVale = D.TIPO_TabVale And
V.TIPO_CodVale = D.TIPO_CodVale And V.VALE_NumVale = D.VALE_NumVale
Where V.VALE_Estado = 'C' And Month(V.VALE_FecEmi) = 9 And
Year(V.VALE_FecEmi) = 2006 And D.PROD_CodProd = '2130080001'
Order By V.VALE_FecEmi Desc

Gracias por tu tiempo y disposición a ayudar y colaborar en el foro

Saludos

PD. Uno siempre aprende algo más de todos UDs.

PD1. Si bien la respuesta es para Alejandro les agradesco a todos por su
tiempo

"Alejandro Mesa" escribió en el
mensaje news:
Mostrar la cita
#8 Alejandro Mesa
07/11/2006 - 18:18 | Informe spam
jcac,

Nadie mejor que tu conoce tu aplicacion, asi que cualquier cambio o solucion
que venga de ti es incuestionable. una sugerencia, no manipules las columnas
en la clausula "where", esto evita que sql server pueda hacer un uso adecuado
de los indices.

Mostrar la cita
V.VALE_FecEmi >= '20060901' and V.VALE_FecEmi < '20061001'

Mostrar la cita
Me pregunto cuales son los indices de esas tablas, restricciones de clave
foranea, de unicidad, etc.?


AMB

"jcac" wrote:

Mostrar la cita
#9 jcac
07/11/2006 - 22:00 | Informe spam
Hola Alejandro

Gracias, si creo que todos llegamos aqui para que quizás nos den una
solución, por ello mismo es que te agradesco tu disposición por ayudar y por
tu tiempo que pienso que a todos nos cuesta.

Te paso los indices y restricciones que hay en esa tabla, de por lo menos
los campos que intervenienenj

index_name index_description
index_keys
IX_DetValesAlm nonclustered located on PRIMARY
SUCR_Codigo, ALMA_Codigo, TIPO_TabVale, TIPO_CodVale, VALE_NumVale
PK__DetValesAlm__075714DC nonclustered, unique, primary key located on
PRIMARY ALMA_Codigo, SUCR_Codigo, VALE_NumVale, DVAL_Item, TIPO_TabVale,
TIPO_CodVale

No tiene otro indice adicional, es una aplicación de terceros, que como
alguien dijo por alli no recuerdo quien, comento que solo lo programan pero
no hacen pruebas como para saber que es mejor para la base solo con que
funcione ya esta hecho asi no sea lo mejor.

Por ello con uds. en este foro he aprendido mucho aunque como dicen a golpes
pero lo he hecho y mi prespectiva con respecto de ver al SQL Server a
cambiado.

Te adjunto el plan de ejecución del query que me pasaste.

Select D.PROD_CodProd, V.VALE_FecEmi, D.DVAL_CostoPS From DetValesAlm D
Inner Join Vales V On D.SUCR_Codigo = V.SUCR_Codigo And D.ALMA_Codigo =
V.ALMA_Codigo And D.TIPO_CodVale = V.TIPO_CodVale And D.VALE_NumVale =
V.VALE_NumVale -- Where D.PROD_CodProd = '2130080001' And V.VALE_Estado =
'C' And Month(V.VALE_FecEmi) = 9 And Year(V.VALE_FecEmi) = 2006 Where
D.PROD_CodProd = '2130080001' And V.VALE_Estado = 'C' And V.VALE_FecEmi >=
'20060901' and V.VALE_FecEmi < '20061001' And V.VALE_FecEmi = (Select
Max(V1.VALE_FecEmi) From DetValesAlm D1 Inner Join Vales V1 On
D1.SUCR_Codigo = V1.SUCR_Codigo And D1.ALMA_Codigo = V1.ALMA_Codigo And
D1.TIPO_CodVale = V1.TIPO_CodVale And D1.VALE_NumVale = V1.VALE_NumVale
Where D1.PROD_CodProd = D.PROD_CodProd And V1.VALE_Estado = V.VALE_Estado
And V1.VALE_FecEmi >= '20060901' and V1.VALE_FecEmi < '20061001')
|--Nested Loops(Inner Join, OUTER REFERENCES:([D].[VALE_NumVale],
[D].[TIPO_CodVale], [D].[ALMA_Codigo], [D].[SUCR_Codigo],
[V1].[VALE_Estado], [Expr1004]) WITH PREFETCH)
|--Hash Match(Aggregate, HASH:([Rank1007], [V1].[VALE_Estado]),
RESIDUAL:([Rank1007]=[Rank1007] AND [V1].[VALE_Estado]=[V1].[VALE_Estado])
DEFINE:([Expr1004]=MAX([V1].[VALE_FecEmi]),
[D].[VALE_NumVale]=ANY([D].[VALE_NumVale]),
[D].[TIPO_CodVale]=ANY([D].[TIPO_CodVale]),
[D].[ALMA_Codigo]=ANY([D].[ALMA_Codigo]),
[D].[SUCR_Codigo]=ANY([D].[SUCR_Codigo]),
[D].[DVAL_CostoPS]=ANY([D].[DVAL_CostoPS]),
[D].[PROD_CodProd]=ANY([D].[PROD_CodProd])))
| |--Hash Match(Inner Join, HASH:([D1].[SUCR_Codigo],
[D1].[ALMA_Codigo], [D1].[TIPO_CodVale],
[D1].[VALE_NumVale])=([V1].[SUCR_Codigo], [V1].[ALMA_Codigo],
[V1].[TIPO_CodVale], [V1].[VALE_NumVale]),
RESIDUAL:((([V1].[SUCR_Codigo]=[D1].[SUCR_Codigo] AND
[V1].[ALMA_Codigo]=[D1].[ALMA_Codigo]) AND
[V1].[TIPO_CodVale]=[D1].[TIPO_CodVale]) AND
[V1].[VALE_NumVale]=[D1].[VALE_NumVale]))
| |--Hash Match(Inner Join,
HASH:([D].[PROD_CodProd])=([D1].[PROD_CodProd]),
RESIDUAL:([D1].[PROD_CodProd]=[D].[PROD_CodProd]))
| | |--Rank
| | | |--Table
Scan(OBJECT:([Layconsa].[dbo].[DetValesAlm] AS [D]),
WHERE:([D].[PROD_CodProd]='2130080001'))
| | |--Table Scan(OBJECT:([Layconsa].[dbo].[DetValesAlm]
AS [D1]))
| |--Clustered Index
Scan(OBJECT:([Layconsa].[dbo].[Vales].[PK__Vales__1EB046D7] AS [V1]),
WHERE:([V1].[VALE_FecEmi]>='Sep 1 2006 12:00AM' AND [V1].[VALE_FecEmi]<'Oct
1 2006 12:00AM'))
|--Clustered Index
Seek(OBJECT:([Layconsa].[dbo].[Vales].[PK__Vales__1EB046D7] AS [V]),
SEEK:([V].[VALE_NumVale]=[D].[VALE_NumVale]),
WHERE:((((((([V].[VALE_FecEmi]=[Expr1004] AND [V].[VALE_FecEmi]>='Sep 1
2006 12:00AM') AND [V].[VALE_FecEmi]<'Oct 1 2006 12:00AM') AND
[V1].[VALE_Estado]=[V].[VALE_Estado]) AND
[V].[SUCR_Codigo]=[D].[SUCR_Codigo]) AND
[V].[ALMA_Codigo]=[D].[ALMA_Codigo]) AND
[V].[TIPO_CodVale]=[D].[TIPO_CodVale]) AND [V].[VALE_Estado]='C') ORDERED
FORWARD)

Aqui te pongo el plan de ejecución del query que te he utilizado finalmente

Select Top 1 D.PROD_CodProd, D.DVAL_CostoPS, V.VALE_FecEmi From Vales V
Inner Join DetValesAlm D On V.SUCR_Codigo = D.SUCR_Codigo And V.ALMA_Codigo
= D.ALMA_Codigo And V.TIPO_TabVale = D.TIPO_TabVale And V.TIPO_CodVale =
D.TIPO_CodVale And V.VALE_NumVale = D.VALE_NumVale Where V.VALE_Estado =
'C' And Month(V.VALE_FecEmi) = 9 And Year(V.VALE_FecEmi) = 2006 And
D.PROD_CodProd = '2130080001' Order By V.VALE_FecEmi Desc
|--Top(1)
|--Filter(WHERE:([D].[PROD_CodProd]='2130080001'))
|--Bookmark Lookup(BOOKMARK:([Bmk1001]),
OBJECT:([Layconsa].[dbo].[DetValesAlm] AS [D]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([V].[VALE_NumVale], [V].[TIPO_CodVale], [V].[TIPO_TabVale],
[V].[ALMA_Codigo], [V].[SUCR_Codigo]) WITH PREFETCH)
|--Sort(ORDER BY:([V].[VALE_FecEmi] DESC))
| |--Clustered Index
Scan(OBJECT:([Layconsa].[dbo].[Vales].[PK__Vales__1EB046D7] AS [V]),
WHERE:(([V].[VALE_Estado]='C' AND datepart(month, [V].[VALE_FecEmi])=9) AND
datepart(year, [V].[VALE_FecEmi]) 06))
|--Index
Seek(OBJECT:([Layconsa].[dbo].[DetValesAlm].[IX_DetValesAlm] AS [D]),
SEEK:([D].[SUCR_Codigo]=[V].[SUCR_Codigo] AND
[D].[ALMA_Codigo]=[V].[ALMA_Codigo] AND
[D].[TIPO_TabVale]=[V].[TIPO_TabVale] AND
[D].[TIPO_CodVale]=[V].[TIPO_CodVale] AND
[D].[VALE_NumVale]=[V].[VALE_NumVale]) ORDERED FORWARD)

Gracias Alejandro una ves más.

Solo como una consulta más, como sabes que manipular columnas en el where no
es bueno, por que por lo menos eso no lo dicen en ningún sitio o es que con
los planes de ejecución es suficiente para uno darse cuenta de ello, ya que
en varios querys que hay en este sistema hay varias consultas que realizan
de esta manera Campo = IsNull(@Campo, Campo) y lei el comentario de que no
era bueno. Si me pudieras indicar una buena bibliografia donde puedo
encontrar todos estos temas de rendimiento mas que todo y como hacer que el
Sql Server trabaje de la mejor manera.

Saludos


"Alejandro Mesa" escribió en el
mensaje news:
Mostrar la cita
#10 Alejandro Mesa
07/11/2006 - 23:04 | Informe spam
jcac,

Dame un par de dias para digerir toda esta informacion y te comento respecto
a los indices actuales y lo que el plan de ejecucion esta haciendo.

Mostrar la cita
Para que SQL Server considere una expresion como un argumento de busqueda,
lo primero es que la columna no se manipule, puesto que si existe un indice
(como por ejemplo por la columna [VALE_FecEmi]) la distribucion de valores en
esa columna esta calculado en base al valor en si y no al resultado de
aplicar una funcion y/o transformacion a la columna. Recuerda que SQL Server
usa las estadisticas de distribucion de los indices para estimar cuantas
filas tendra el resultado y en base a eso (tambien a otros parametros)
escojera que tipo de operacion realizar. Si el valor de la expresion no puede
ser usado para buscar en las estadisticas, entonces SQL Server no hara el
intento de usar ese indice, al menos no de forma optima. La forma de la
expresion debe ser:

<columna> <operador> <variable o constante>
<variable o constante> <operador> <columna>

Veamos un ejemplo concreto:

use northwind
go

set showplan_text on
go

declare @orderid int

set @orderid = null

select
*
from
dbo.orders
where
orderid = isnull(@orderid, orderid)

select
*
from
dbo.orders
where
orderid between coalesce(@orderid, convert(int, 0x80000000)) and
coalesce(@orderid, convert(int, 0x7FFFFFFF))
go

set showplan_text off
go

Planes de ejecucion estimados:

Query - 1

|--Nested Loops(Inner Join, OUTER
REFERENCES:([northwind].[dbo].[Orders].[OrderID]))
|--Index Scan(OBJECT:([northwind].[dbo].[Orders].[EmployeeID]),
WHERE:([northwind].[dbo].[Orders].[OrderID]=isnull([@orderid],[northwind].[dbo].[Orders].[OrderID])))
|--Clustered Index
Seek(OBJECT:([northwind].[dbo].[Orders].[PK_Orders]),
SEEK:([northwind].[dbo].[Orders].[OrderID]=[northwind].[dbo].[Orders].[OrderID]) LOOKUP ORDERED FORWARD)

Query - 2

|--Clustered Index Seek(OBJECT:([northwind].[dbo].[Orders].[PK_Orders]),
SEEK:([northwind].[dbo].[Orders].[OrderID] >= CASE WHEN [@orderid] IS NOT
NULL THEN [@orderid] ELSE (-2147483648) END AND
[northwind].[dbo].[Orders].[OrderID] <= CASE WHEN [@orderid] IS NOT NULL THEN
[@orderid] ELSE (2147483647) END) ORDERED FORWARD)

Costos estimados:

query 1 - 68%
query 2 - 32%

Como vez, la segunda sentencia tiene menos costo asociado porque SQL Server
escojio hacer un "index seek" en el indice pk_orders. Fijate en el plan de la
primera sentencia, que te parece ese plan?, horrible.

Te paso unos cuantos links para que leas al respecto.

INF: Los argumentos de búsqueda que determinan distribución paginan uso
http://support.microsoft.com/kb/169642/es

Ajuste y optimización del rendimiento de MS SQL Server para programadores,
primera parte: Introducción a los aspectos de rendimiento
http://www.microsoft.com/latam/tech...005/art02/

Estadísticas de distribución en SQL Server 2000 (I)
http://www.helpdna.net/colab02.htm

Estadísticas de Distribución en SQL Server 2000 (2)
http://www.configuracionesintegrale...articulo35

Estadísticas utilizadas por el optimizador de consultas de Microsoft SQL
Server 2000
http://www.microsoft.com/spanish/ms...tquery.asp

Ajuste del rendimiento de las consultas (SQL Server Mobile)
http://msdn2.microsoft.com/es-es/li...72984.aspx


AMB


"jcac" wrote:

Mostrar la cita
Ads by Google
Search Busqueda sugerida