Optimizar Indices

06/10/2005 - 19:29 por Pao | Informe spam
Tengo una duda:
Como puedo saber cual de mis indices es el más usando, así tambien mis
indices estadisticos.
_WA

Sucede que tengo una aplicación que constantemente hace este tipo de query's:
use sms_cliente
select count(*) from sms_res_enviadas
where re_hora_ing <= '10/06/2005 11:23:42' and re_operadora = 'P' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 = 0
go
use sms_cliente
select count(*) from sms_res_enviadas
where re_hora_ing <= '10/06/2005 11:23:42' and re_operadora ='B' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 = 0


Adjunto planes de ejecución: se supone que usa los indices pero yo no tengo
definido ningun indice que empiece con re_hora_ing o es por el de
re_codigo???

Indices:
sp_helpindex sms_res_enviadas
re_fechaing_idx nonclustered located on PRIMARY re_fecha_ing
re_recibido_idx nonclustered located on PRIMARY re_cod_recibido
re_transmitir_idx nonclustered located on PRIMARY re_codigo, re_operadora,
re_hora_ing, re_estado
sms_resenviadas_key clustered, unique located on PRIMARY re_codigo

Indices estadisticos:
_WA_Sys_re_hora_ing_79A81403
_WA_Sys_re_operadora_79A81403
_WA_Sys_re_estado_79A81403
_WA_Sys_re_fecha_env_79A81403
_WA_Sys_re_telefono_79A81403
_WA_Sys_re_hora_env_79A81403
_WA_Sys_re_mensaje_79A81403

Row Tabla: 520.000

Favor su ayuda que no entiendo este comportamiento
StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
set showplan_all on 14 1 0 1 SETON 0

(1 row(s) affected)

StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
set showplan_text on 15 1 0 1 SETON 0

(1 row(s) affected)

StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
SET STATISTICS IO on 16 1 0 1 SETSTATON 0

(1 row(s) affected)

StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
SET STATISTICS TIME on 17 1 0 1 SETSTATON 0

(1 row(s) affected)

StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
use sms_cliente 18 1 0 1 DBOPEN 0

select count(*) from sms_res_enviadas
where re_hora_ing <= '10/06/2005 11:23:42' and re_operadora = 'P' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 =
0 19 2 0 2 1.0 2.998153 SELECT 0
|--Compute Scalar(DEFINE:([Expr1002]=Convert([Expr1005]))) 19 3 2 Compute
Scalar Compute
Scalar DEFINE:([Expr1002]=Convert([Expr1005])) [Expr1002]=Convert([Expr1005]) 1.0 0.0 0.00000025 11 2.998153 [Expr1002] PLAN_ROW 0 1.0
|--Stream Aggregate(DEFINE:([Expr1005]=Count(*))) 19 4 3 Stream
Aggregate Aggregate [Expr1005]=Count(*) 1.0 0.0 0.00000025 11 2.998153 [Expr1005] PLAN_ROW 0 1.0
|--Index
Scan(OBJECT:([sms_cliente].[dbo].[sms_res_enviadas].[re_transmitir_idx]),
WHERE:((([sms_res_enviadas].[re_hora_ing]<='Oct 6 2005 11:23AM' AND
[sms_res_enviadas].[re_operadora]='P') AND
[sms_res_enviadas].[re_estado]='PEN') AND [sms_r 19 5 4 Index Scan Index
Scan OBJECT:([sms_cliente].[dbo].[sms_res_enviadas].[re_transmitir_idx]),
WHERE:((([sms_res_enviadas].[re_hora_ing]<='Oct 6 2005 11:23AM' AND
[sms_res_enviadas].[re_operadora]='P') AND
[sms_res_enviadas].[re_estado]='PEN') AND
[sms_res_enviadas].[re_codigo]-[ [sms_res_enviadas].[re_codigo],
[sms_res_enviadas].[re_estado], [sms_res_enviadas].[re_operadora],
[sms_res_enviadas].[re_hora_ing] 1.0 0.6721226 0.28607884 41 1.9164028 [sms_res_enviadas].[re_codigo],
[sms_res_enviadas].[re_estado], [sms_res_enviadas].[re_operadora],
[sms_res_enviadas].[re_hora_ing] PLAN_ROW 0 1.0

(5 row(s) affected)

StmtText StmtId NodeId Parent PhysicalOp LogicalOp Argument DefinedValues EstimateRows EstimateIO EstimateCPU AvgRowSize TotalSubtreeCost OutputList Warnings Type Parallel EstimateExecutions
use sms_cliente 20 1 0 1 DBOPEN 0

select count(*) from sms_res_enviadas
where re_hora_ing <= '10/06/2005 11:23:42' and re_operadora ='B' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 =
0 21 2 0 2 1.0 2.998153 SELECT 0
|--Compute Scalar(DEFINE:([Expr1002]=Convert([Expr1005]))) 21 3 2 Compute
Scalar Compute
Scalar DEFINE:([Expr1002]=Convert([Expr1005])) [Expr1002]=Convert([Expr1005]) 1.0 0.0 0.00000025 11 2.998153 [Expr1002] PLAN_ROW 0 1.0
|--Stream Aggregate(DEFINE:([Expr1005]=Count(*))) 21 4 3 Stream
Aggregate Aggregate [Expr1005]=Count(*) 1.0 0.0 0.00000025 11 2.998153 [Expr1005] PLAN_ROW 0 1.0
|--Index
Scan(OBJECT:([sms_cliente].[dbo].[sms_res_enviadas].[re_transmitir_idx]),
WHERE:((([sms_res_enviadas].[re_hora_ing]<='Oct 6 2005 11:23AM' AND
[sms_res_enviadas].[re_operadora]='B') AND
[sms_res_enviadas].[re_estado]='PEN') AND [sms_r 21 5 4 Index Scan Index
Scan OBJECT:([sms_cliente].[dbo].[sms_res_enviadas].[re_transmitir_idx]),
WHERE:((([sms_res_enviadas].[re_hora_ing]<='Oct 6 2005 11:23AM' AND
[sms_res_enviadas].[re_operadora]='B') AND
[sms_res_enviadas].[re_estado]='PEN') AND
[sms_res_enviadas].[re_codigo]-[ [sms_res_enviadas].[re_codigo],
[sms_res_enviadas].[re_estado], [sms_res_enviadas].[re_operadora],
[sms_res_enviadas].[re_hora_ing] 1.0 0.6721226 0.28607884 41 1.9164028 [sms_res_enviadas].[re_codigo],
[sms_res_enviadas].[re_estado], [sms_res_enviadas].[re_operadora],
[sms_res_enviadas].[re_hora_ing] PLAN_ROW 0 1.0

(5 row(s) affected)

Preguntas similare

Leer las respuestas

#11 Maxi
07/10/2005 - 21:38 | Informe spam
Hola, ojo, no es lo mismo un table scan que un index Scan!! pero esta
haciendo un Scan :(


Salu2
Maxi


"Pao" escribió en el mensaje
news:
Mostrar la cita
#12 Alejandro Mesa
07/10/2005 - 23:10 | Informe spam
Pao,

Mostrar la cita
Esta expresion es la que evita que sql server use el indice:

[sms_cliente].[dbo].[sms_res_enviadas].[re_transmitir_idx]

porque la columna [re_codigo], es la primera del conjunto de columnas que
conforman la clave de ese indice.

Mostrar la cita
En pocas palabras, las estadisticas de distribucion de los valores de las
columnas que conforman la clave del indice, nos dan una idea de cuan
selectivo es el indice para un acierto valor, o si prefieres asi, que
cantidad de filas serian seleccionadas dado un valor especifico de esas
columnas. Si las estadisticas dan que son muchas filas, entonces sql server
prefiere no usar el indice porque seria mas costoso scanear el indice y por
cada fila ir a la tabla o al indice clustered a buscar el valor de las
columnas que aparecen en la lista de columnas de la clausula "select".

DBCC SHOW_STATISTICS (sms_res_enviadas, re_transmitir_idx)

Statistics Used by the Query Optimizer in Microsoft SQL Server 200
http://msdn.microsoft.com/library/d...frame=true


AMB

"Pao" wrote:

Mostrar la cita
#13 Alejandro Mesa
07/10/2005 - 23:15 | Informe spam
Correccion,

Vez Maxi, ahora soy yo el que usa la expresion incorrecta.

Mostrar la cita
Esta expresion es la que evita que sql server tome en cuenta el indice para
hacer un "index seek" en el indice indicado. Si esta expresion se cambia de
forma que no se manipule la columna, entonces sql server podria analizar el
indice para ver si se puede o no hacer un "index seek".


AMB

"Alejandro Mesa" wrote:

Mostrar la cita
#14 Pao
10/10/2005 - 17:39 | Informe spam
Ok, Alexandro voy a conversar con el proveedor sobre esta expresión que no
deja usar el indice correcto, ya que ellos nos enviaron una solución creando
otro indice por estado, te adjunto.

use sms_cliente
go
/* Creacion de Indice re_estado_idx sobre la tabla sms_res_enviadas */
/* Campo: re_estado */
create index re_estado_idx on sms_res_enviadas (re_estado)
go

El cpu mejoro notablemente y ya no esta al 100% muy bajo 30 a 40% como mucho
y por ende el contador de Processor Queue Lenght esta como maximo 2 pero por
periodos muy cortos; sin embargo yo había habilitado los trace deadlock y
noto que ahora tengo demasiados deadlock y veo que es entre el indice nuevo
con el indice que debería tomar pero por la expresión del argumento no lo
deja. Esto tampoco debe ser bueno, que me sugieres que se haga. Muchas gracias
Mira los deadlock:
y ahora como cambió el plan de ejecución:
****StmtText
select count(*) from sms_res_enviadas
where re_hora_ing <= '10/07/2005 13:38:21' and re_operadora = 'P' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 = 0

(1 row(s) affected)

StmtText
|--Compute Scalar(DEFINE:([Expr1002]=Convert([Expr1005])))
|--Stream Aggregate(DEFINE:([Expr1005]=Count(*)))
|--Filter(WHERE:([sms_res_enviadas].[re_operadora]='P' AND
[sms_res_enviadas].[re_hora_ing]<='Oct 7 2005 1:38PM'))
|--Bookmark Lookup(BOOKMARK:([Bmk1000]),
OBJECT:([sms_cliente].[dbo].[sms_res_enviadas]))
|--Index
Seek(OBJECT:([sms_cliente].[dbo].[sms_res_enviadas].[re_estado_idx]),
SEEK:([sms_res_enviadas].[re_estado]='PEN'),
WHERE:([sms_res_enviadas].[re_codigo]-[sms_res_enviadas].[re_codigo]/1*1=0)
ORDERED FORWARD)

*******
KEY: 7:2041058307:8
7: Base: sms_cliente
2041058307:Tabla:sms_res_enviadas
Indices:
1 sms_resenviadas_key 2041058307
2 re_transmitir_idx 2041058307
3 re_fechaing_idx 2041058307
4 re_recibido_idx 2041058307
5 _WA_Sys_re_hora_ing_79A81403 2041058307
6 _WA_Sys_re_operadora_79A81403 2041058307
7 _WA_Sys_re_estado_79A81403 2041058307
8 re_estado_idx
ERRORLOG
Deadlock encountered Printing deadlock information
2005-10-07 10:20:06.87 spid4
2005-10-07 10:20:06.87 spid4 Wait-for graph
2005-10-07 10:20:06.87 spid4
2005-10-07 10:20:06.87 spid4 Node:1
2005-10-07 10:20:06.87 spid4 KEY: 7:2041058307:8 (1e01aa86b623)
CleanCnt:1 Mode: S Flags: 0x0
2005-10-07 10:20:06.87 spid4 Grant List 0::
2005-10-07 10:20:06.87 spid4 Owner:0x42bc6be0 Mode: S Flg:0x0
Ref:1 Life:00000000 SPID:55 ECID:0
2005-10-07 10:20:06.87 spid4 SPID: 55 ECID: 0 Statement Type: SELECT
Line #: 2
2005-10-07 10:20:06.87 spid4 Input Buf: Language Event: use sms_cliente
select min(re_codigo) from sms_res_enviadas
where re_hora_ing <= '10/07/2005 10:19:55' and re_operadora = 'P' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 = 0 and re_codigo > 0
2005-10-07 10:20:06.89 spid4 Requested By:
2005-10-07 10:20:06.89 spid4 ResType:LockOwner Stype:'OR' Mode: X
SPID:54 ECID:0 Ec:(0x42E6B510) Value:0x42bdfd20 Cost:(0/A0)
2005-10-07 10:20:06.89 spid4
2005-10-07 10:20:06.89 spid4 Node:2
2005-10-07 10:20:06.89 spid4 KEY: 7:2041058307:1 (3b0088121d04)
CleanCnt:1 Mode: X Flags: 0x0
2005-10-07 10:20:06.89 spid4 Grant List 1::
2005-10-07 10:20:06.89 spid4 Owner:0x42be5280 Mode: X Flg:0x0
Ref:0 Life:02000000 SPID:54 ECID:0
2005-10-07 10:20:06.89 spid4 SPID: 54 ECID: 0 Statement Type: UPDATE
Line #: 1
2005-10-07 10:20:06.89 spid4 Input Buf: Language Event: use sms_cliente
begin tran
update sms_res_enviadas
set re_fecha_env = '10/07/2005', re_hora_env = '10/07/2005 10:19:55',
re_messageid = '2dfb1bd8', re_estado = 'ENV'
where re_codigo = 521275
commit tran
2005-10-07 10:20:06.89 spid4 Requested By:
2005-10-07 10:20:06.89 spid4 ResType:LockOwner Stype:'OR' Mode: S
SPID:55 ECID:0 Ec:(0x42E77510) Value:0x42bc64e0 Cost:(0/0)
2005-10-07 10:20:06.89 spid4 Victim Resource Owner:
2005-10-07 10:20:06.89 spid4 ResType:LockOwner Stype:'OR' Mode: S
SPID:55 ECID:0 Ec:(0x42E77510) Value:0x42bc64e0 Cost:(0/0)
2005-10-07 10:20:06.89 spid4
2005-10-07 10:20:06.89 spid4 End deadlock search 35 ... a deadlock was
found.
2005-10-07 10:20:06.89 spid4 -


Deadlock encountered Printing deadlock information
2005-10-07 13:38:30.31 spid4
2005-10-07 13:38:30.31 spid4 Wait-for graph
2005-10-07 13:38:30.31 spid4
2005-10-07 13:38:30.31 spid4 Node:1
2005-10-07 13:38:30.31 spid4 KEY: 7:2041058307:1 (bc003df65175)
CleanCnt:1 Mode: X Flags: 0x0
2005-10-07 13:38:30.31 spid4 Grant List 1::
2005-10-07 13:38:30.31 spid4 Owner:0x5a913500 Mode: X Flg:0x0
Ref:0 Life:02000000 SPID:58 ECID:0
2005-10-07 13:38:30.31 spid4 SPID: 58 ECID: 0 Statement Type: UPDATE
Line #: 1
2005-10-07 13:38:30.33 spid4 Input Buf: Language Event: use sms_cliente
begin tran
update sms_res_enviadas
set re_fecha_env = '10/07/2005', re_hora_env = '10/07/2005 13:38:21',
re_messageid = '416B78B8', re_estado = 'ENV'
where re_codigo = 521660
commit tran
2005-10-07 13:38:30.33 spid4 Requested By:
2005-10-07 13:38:30.33 spid4 ResType:LockOwner Stype:'OR' Mode: S
SPID:55 ECID:0 Ec:(0x42E77510) Value:0x5a612a20 Cost:(0/0)
2005-10-07 13:38:30.33 spid4
2005-10-07 13:38:30.33 spid4 Node:2
2005-10-07 13:38:30.33 spid4 KEY: 7:2041058307:8 (9f011f62fa52)
CleanCnt:1 Mode: S Flags: 0x0
2005-10-07 13:38:30.33 spid4 Grant List 0::
2005-10-07 13:38:30.33 spid4 Owner:0x42bcf100 Mode: S Flg:0x0
Ref:1 Life:00000000 SPID:55 ECID:0
2005-10-07 13:38:30.33 spid4 SPID: 55 ECID: 0 Statement Type: SELECT
Line #: 2
2005-10-07 13:38:30.33 spid4 Input Buf: Language Event: use sms_cliente
select count(*) from sms_res_enviadas
where re_hora_ing <= '10/07/2005 13:38:21' and re_operadora = 'P' and
re_estado = 'PEN' and re_codigo - re_codigo/1*1 = 0
2005-10-07 13:38:30.33 spid4 Requested By:
2005-10-07 13:38:30.33 spid4 ResType:LockOwner Stype:'OR' Mode: X
SPID:58 ECID:0 Ec:(0x446BF510) Value:0x42bdaf60 Cost:(0/A0)
2005-10-07 13:38:30.33 spid4 Victim Resource Owner:
2005-10-07 13:38:30.33 spid4 ResType:LockOwner Stype:'OR' Mode: S
SPID:55 ECID:0 Ec:(0x42E77510) Value:0x5a612a20 Cost:(0/0)
2005-10-07 13:38:30.33 spid4
2005-10-07 13:38:30.33 spid4 End deadlock search 43 ... a deadlock was
found.
2005-10-07 13:38:30.33 spid4 -

"Alejandro Mesa" wrote:

Mostrar la cita
#15 Alejandro Mesa
10/10/2005 - 22:37 | Informe spam
Pao,

Como te dije antes, la expression no deja que se use el indice de forma
correcta y por lo tanto sql server decide hacer un scan del indice en vez de
un seek. Si la expresion no estuviese manipulando la columna, por ejemplo:

and re_codigo = 45

te daras cuenta que sql server usaria este indice sin necesidad de hacer un
"Bookmark Lookup" (una vez que encuentra el indice, toma el valor de la clave
del indice clustered asociado o el rowid en caso de no tener indice clustered
y busca el valor en la tabla) y esto haria que la operacion fuese mucho mas
rapido. Has un test de lo que te digo, ve cual es el plan ejecucion de la
sentencia:

select count(*)
from dbo.sms_res_enviadas
where
re_hora_ing <= '10/07/2005 13:38:21'
and re_operadora = 'P'
and re_estado = 'PEN'
and re_codigo = 45

y posteala aca para verlo.

En cuanto a los deadlocks, es obvio que el nuevo indice esta formando parte
de este problema.

Mostrar la cita
en ambos casos se esta haciendo un lock de tipo KEY y los indices
involucrados son el indice 1 (ms_resenviadas_key) y el indice 8
(re_estado_idx). Debes tener un par de procesos accesando estos recursos en
diferente orden, un proceso actualiza la tabla y despues la lee en la misma
transaccion y el otro proceso la lee y luego la actualiza, provocando que
cuando una sentencia necesita hacer un lock de un indice, la otra sentencia
del otro proceso ya tiene un lock sobre ese indice y espera para hacer un
lock de otro indice, el cual esta lock por la otra transaccion. Una
sugerencia es tratar de accesar los recursos en el mismo orden, ejemplo:

select ...
update ...

y si el select no necesita estar dentro de la transaccion, entonces sacalo.



AMB


"Pao" wrote:

Mostrar la cita
Ads by Google
Search Busqueda sugerida