OT - Consulta sobre uso de indices o no

10/05/2007 - 17:18 por jcac | Informe spam
Hola lista

Ayer asisti a una presentacion de DB2, en la que indicaron que según su
optimizador, que indican es inteligente, hace las siguientes difenrencias
por ejemplo:

si tenemos una tabla de 1 millon de registros y esta esta indizada por por
el campo1 que no es pk, entonces mantiene estadisticas del indice, lo que
pienso que el sql server hace lo mismo o si estoy equivocado corrijanme por
favor.

ahora viendo un caso practico en dicha tabla tenemos distintos datos, en
campo1 exiten datos como 'Blanco', 'Negro', 'Amarilo', etc, teniendo que
estos son repetitivos en muchos casos un color es predominante y en otros
no, lo que indican es que su optimizador inteligente hace los siguiente:

si el dato que se busca por ejemplo:

select campo1, campo2, campo3 from tabla where campo1 = 'Blanco', pero este
color tiene digamos 10 registros en la tabla de 1 millon, hara uso del
indice por dicho campo, en el caso:

select campo1, campo2, campo3 from tabla where campo1 = 'Negro', pero este
color existe dentro de la tabla en 900 mil registros no hara uso del indice
para hacer la busqueda sino que hara un barrido de toda la tabla debido a
que l mayoria de registros contienen dicha condicion, e indican que haciendo
de dicha manera es mucho mas rapido que hacer uso del indice.

despues de haberles contado un poco lo que me han dicho lo cual no lo puedo
comprobar debido a que no cuento con db2, mi duda es como sql server realiza
las busquedas si la tabla tiene indice por el campo siempre lo usa, o lo
deja de usar???

es casi como una duda de existencialidad

saludos

Preguntas similare

Leer las respuestas

#11 jcac
14/05/2007 - 14:48 | Informe spam
Alejandro y Javier,

Les agradesco mucho lo que me han explicado en estos días por lo que
considero un conocimiento que han compartido que es invaluable.

Saludos

Juan Carlos


"Javier Loria" escribió en el mensaje
news:
Hola Alejandro:
Gracias...
Saludos,

Javier Loria
Costa Rica (MVP)
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.

"Alejandro Mesa" wrote in
message news:
jcac,

StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Negro'

StmtText
|--Bookmark Lookup(BOOKMARK:([Bmk1000]),
OBJECT:([Documental].[dbo].[prueba]))
|--Index
Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)



Ya lo explique en otro e-mail. La tabla tiene un indice por [campo2] y
solo
7 filas machan esa expresion (where campo2 = 'Negro'). El indice es
bastante
selectivo (pocas filas para una expresion en concreto) y por lo tanto es
menos costoso buscar en ese indice por [campo2], tomar el valor de la
clave
primaria e ir a buscar el resto de la data en el indice clustered. Esta
accion se llama "bookmark lookup". Exactamente con esta indicado en el
plan
de ejecucion.

StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'

StmtText
|--Clustered Index
Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
WHERE:([prueba].[campo2]='Blanco'))



Demasiadas filas machan esa expresion (where campo2 = 'Blanco'), asi que
en
vez de buscar en el indice nonclustered, por [campo2], y luego ir a
buscar el
resto de la data en el indice clustered (PK__prueba__20C1E124, y por
favor no
confundas indice con clave primaria), SQL Server decide que es menos
costoso
escanear el indice clustered y encontrar la data deseada. Tal como se ve
en
el plan de ejecucion, el indice nonclustered por [campo2] no es de ayuda
alguna.

drop index prueba.id_prueba_campo2
go

y obtuve el mismo resultado que cuando lo tenia
StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'

StmtText
|--Clustered Index
Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
WHERE:([prueba].[campo2]='Blanco'))



Si borras el indice nonclustered, entonces solamente queda un solo lugar
donde buscar la data y es en el indice clustered (recuerda que los nodos
hojas de un indice clustered son las paginas de data).

alter table prueba drop constraint PK__prueba__20C1E124
go

y obtuve el siguiente resultado

StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'

StmtText
|--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
WHERE:([prueba].[campo2]=[@1]))



Bueno, ya no tienes indice alguno, ahora solo queda la tabla sin indice
clustered (heap). Donde mas puede buscarse la data que escaneando la
propia
tabla. Si una tabla tiene indice clustered, entonces este sera usado. Si
la
tabla no tiene indice clustered, entonces la tabla sera usada.


AMB


"jcac" wrote:

Hola Javier,

Muchas gracias por tu paciencia y disposición para ver este tema.

Bueno hice la prueba para ver dicho comportamiento y aqui tengo los
resultados:

StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Negro'

StmtText
|--Bookmark Lookup(BOOKMARK:([Bmk1000]),
OBJECT:([Documental].[dbo].[prueba]))
|--Index
Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)


StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'

StmtText
|--Clustered Index
Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
WHERE:([prueba].[campo2]='Blanco'))

Como veo aqui no usa el indice del campo, pero hace uso del indice de la
tabla, esto no va en contra del rendimiento???

Hice una prueba mas y fue borrar el indice id_prueba_campo2

drop index prueba.id_prueba_campo2
go

y obtuve el mismo resultado que cuando lo tenia
StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'

StmtText
|--Clustered Index
Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
WHERE:([prueba].[campo2]='Blanco'))

despues he borrado la pk

alter table prueba drop constraint PK__prueba__20C1E124
go

y obtuve el siguiente resultado

StmtText
select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'

StmtText
|--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
WHERE:([prueba].[campo2]=[@1]))

el cual tiene el mismo tiempo de respuesta como si hubiera tenido la pk
en
la tabla

si bien lo que estoy buscando es como SQL Server puede diferenciar entre
una
cosa u otra, donde puedo encontrar infromación acerca de ello y poder
hacer
prueba, tambien considero que son pruebas aisladas pero pienso por lo
menos
que daran una idea de lo que podria hacer en una bd en produccion,
siguiendo
la misma tematica es donde podria tener informacion de como SQL Server
hace
uso de indices o no???? cosa que así se puede comprender mucho mas que
es
bueno o malo y cuales son las mejores tecnicas que hay que aplicar.

Espero no aburrirte con esto, es solo que la curiosidad es grande y el
hecho
de poder comparar hoy en día es una vemtaja pero para hacerlo hay que
conocer la herramienta que hace y que deja de hacer.

Saludos




"Javier Loria" escribió en el mensaje
news:
> Hola:
> SQL 2000 y SQL 2005. No puedo probar con una 2000 pero debe tener
> el
> mismo comportamiento 2005.
> Lo que ves en que en tu caso, porque el codigo lo simplificaste
> "demasiado" el segundo indice se quedo como un "indice cubierto"
> (tiene
> todos los datos de la fila, ya que tienes todos los campos en el
> indice.
> Veamos que pasaria cuando agregas mas columnas:
> ==>>> > drop table prueba
>
> create table prueba(campo1 int primary key
> , campo2 varchar(100) NOT NULL
> , campo3 char(100) NOT NULL
> )
> go
> create index id_prueba_campo2 on prueba(campo2)
> go
> declare @i int
> set @i=0
> while @i <= 10000
> begin
> insert into prueba values(@i, 'Blanco', '')
> set @i=@i+1
> continue
> end
> go
> update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100, 1000,
> 10000, 100000, 1000000)
> go
>
> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
> sea
> uso el indice!!!
> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
> ==>>> > Espero se entienda.
> Saludos,
>
>
> Javier Loria
> Costa Rica (MVP)
> Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
> que pueda ser copiado y pegado al Query Analizer.
> La version de SQL y Service Pack tambien ayuda.
>
>
>
> "jcac" wrote in message
> news:
>> Hola Javier,
>>
>> Quizas me podrias indicar desde que versión SQL Server hace uso de
>> esto???, ya que hice una prueba, de este tipo
>>
>> create table prueba(campo1 int primary key, campo2 varchar(100))
>> go
>> create index id_prueba_campo2 on prueba(campo2)
>> go
>> declare @i int
>> set @i=0
>> while @i <= 1000000
>> begin
>> insert into prueba values(@i, 'Blanco')
>> continue
>> end
>> go
>> update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100,.
>> 1000,
>> 10000, 100000, 1000000)
>> go
>>
>> ejecute esta dos consultas
>> select campo1, campo2 from prueba where campo2 = 'Negro'
>> teniendo un tiempo de respuesta muy rapido por menos del segundo,
>> adicionalmente vi el plan de ejecucionm y en definitiva hacia uso del
>> indice, luego lo hice con esta otra
>> select campo1, campo2 from prueba where campo2 = 'Blanco'
>> teniendo un tiempo de respuesta de aproximadamente unos 2 minutos y
>> 28
>> segundos en su plan de ejecución vi que igualmente hacia uso del
>> indice.
>>
>> la versión de SQL Server que utilizo pra realizar esta prueba es la
>> MSDE
>> 2000 con SP4.
>>
>> Saludos
>>
>>
>> "Javier Loria" escribió en el mensaje
>> news:
>>> Hola:
>>> La forma en que se comporta SQL es mas o menos la que
>>> describiste.
>>> Si hay muchas filas que cumplen la igualdad no usara el indices y
>>> si
>>> hay pocas si.
>>> Por eso es importante hacer uso de indices con columns
>>> distintivas.
>>> Saludos,
>>>
>>> Javier Loria
>>> Costa Rica (MVP)
>>> Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
>>> que pueda ser copiado y pegado al Query Analizer.
>>> La version de SQL y Service Pack tambien ayuda.
>>>
>>> "jcac" wrote in message
>>> news:
>>>> Hola lista
>>>>
>>>> Ayer asisti a una presentacion de DB2, en la que indicaron que
>>>> según su
>>>> optimizador, que indican es inteligente, hace las siguientes
>>>> difenrencias por ejemplo:
>>>>
>>>> si tenemos una tabla de 1 millon de registros y esta esta indizada
>>>> por
>>>> por el campo1 que no es pk, entonces mantiene estadisticas del
>>>> indice,
>>>> lo que pienso que el sql server hace lo mismo o si estoy equivocado
>>>> corrijanme por favor.
>>>>
>>>> ahora viendo un caso practico en dicha tabla tenemos distintos
>>>> datos,
>>>> en campo1 exiten datos como 'Blanco', 'Negro', 'Amarilo', etc,
>>>> teniendo
>>>> que estos son repetitivos en muchos casos un color es predominante
>>>> y
>>>> en otros no, lo que indican es que su optimizador inteligente hace
>>>> los
>>>> siguiente:
>>>>
>>>> si el dato que se busca por ejemplo:
>>>>
>>>> select campo1, campo2, campo3 from tabla where campo1 = 'Blanco',
>>>> pero
>>>> este color tiene digamos 10 registros en la tabla de 1 millon, hara
>>>> uso
>>>> del indice por dicho campo, en el caso:
>>>>
>>>> select campo1, campo2, campo3 from tabla where campo1 = 'Negro',
>>>> pero
>>>> este color existe dentro de la tabla en 900 mil registros no hara
>>>> uso
>>>> del indice para hacer la busqueda sino que hara un barrido de toda
>>>> la
>>>> tabla debido a que l mayoria de registros contienen dicha
>>>> condicion, e
>>>> indican que haciendo de dicha manera es mucho mas rapido que hacer
>>>> uso
>>>> del indice.
>>>>
>>>> despues de haberles contado un poco lo que me han dicho lo cual no
>>>> lo
>>>> puedo comprobar debido a que no cuento con db2, mi duda es como sql
>>>> server realiza las busquedas si la tabla tiene indice por el campo
>>>> siempre lo usa, o lo deja de usar???
>>>>
>>>> es casi como una duda de existencialidad
>>>>
>>>> saludos
>>>>
>>>>
>>>
>>
>>
>








Respuesta Responder a este mensaje
#12 jcac
14/05/2007 - 14:49 | Informe spam
José,

Como indicas me estoy dando cuenta es como trabaja SQL Server y eso es algo
muy importante, muchas gracias.

Saludos



"Jose Mariano Alvarez"
escribió en el
mensaje news:
En el post , DIJO
.

despues de haberles contado un poco lo que me han dicho lo cual no lo
puedo
comprobar debido a que no cuento con db2, mi duda es como sql server
realiza
las busquedas si la tabla tiene indice por el campo siempre lo usa, o lo
deja de usar???






Sql server hace practicamente lo mismo.

Usa las estadisticas para determinar si un indice le sirve en ese caso
determinado.

Pero por supuesto hay muchos mas criterios y condiciones a tener en
cuenta pero en lineas generales es asi. El planificador esta basado en
costos y uno de esos costos es ese que tu comentas.

Saludos



Saludos
Ing. Jose Mariano Alvarez


(Cambia los ceros por O y saca lo que sobra)


IMPORTANTE

Por favor traten de indicar la versión de SQL y Service Pack.
La inclusión de (CREATE, INSERTS, etc.) para poder reproducir el
problema también ayuda.
Respuesta Responder a este mensaje
#13 Alejandro Mesa
14/05/2007 - 16:51 | Informe spam
Hoal Javier,

No hay de que.

Saludo a todos por Costa Rica,
Alejandro Mesa


"Javier Loria" wrote:

Hola Alejandro:
Gracias...
Saludos,

Javier Loria
Costa Rica (MVP)
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.

"Alejandro Mesa" wrote in message
news:
> jcac,
>
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>
>> StmtText
>> |--Bookmark Lookup(BOOKMARK:([Bmk1000]),
>> OBJECT:([Documental].[dbo].[prueba]))
>> |--Index
>> Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
>> SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)
>
> Ya lo explique en otro e-mail. La tabla tiene un indice por [campo2] y
> solo
> 7 filas machan esa expresion (where campo2 = 'Negro'). El indice es
> bastante
> selectivo (pocas filas para una expresion en concreto) y por lo tanto es
> menos costoso buscar en ese indice por [campo2], tomar el valor de la
> clave
> primaria e ir a buscar el resto de la data en el indice clustered. Esta
> accion se llama "bookmark lookup". Exactamente con esta indicado en el
> plan
> de ejecucion.
>
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>
>> StmtText
>> |--Clustered Index
>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>> WHERE:([prueba].[campo2]='Blanco'))
>
> Demasiadas filas machan esa expresion (where campo2 = 'Blanco'), asi que
> en
> vez de buscar en el indice nonclustered, por [campo2], y luego ir a buscar
> el
> resto de la data en el indice clustered (PK__prueba__20C1E124, y por favor
> no
> confundas indice con clave primaria), SQL Server decide que es menos
> costoso
> escanear el indice clustered y encontrar la data deseada. Tal como se ve
> en
> el plan de ejecucion, el indice nonclustered por [campo2] no es de ayuda
> alguna.
>
>> drop index prueba.id_prueba_campo2
>> go
>>
>> y obtuve el mismo resultado que cuando lo tenia
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>
>> StmtText
>> |--Clustered Index
>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>> WHERE:([prueba].[campo2]='Blanco'))
>
> Si borras el indice nonclustered, entonces solamente queda un solo lugar
> donde buscar la data y es en el indice clustered (recuerda que los nodos
> hojas de un indice clustered son las paginas de data).
>
>> alter table prueba drop constraint PK__prueba__20C1E124
>> go
>>
>> y obtuve el siguiente resultado
>>
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>
>> StmtText
>> |--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
>> WHERE:([prueba].[campo2]=[@1]))
>
> Bueno, ya no tienes indice alguno, ahora solo queda la tabla sin indice
> clustered (heap). Donde mas puede buscarse la data que escaneando la
> propia
> tabla. Si una tabla tiene indice clustered, entonces este sera usado. Si
> la
> tabla no tiene indice clustered, entonces la tabla sera usada.
>
>
> AMB
>
>
> "jcac" wrote:
>
>> Hola Javier,
>>
>> Muchas gracias por tu paciencia y disposición para ver este tema.
>>
>> Bueno hice la prueba para ver dicho comportamiento y aqui tengo los
>> resultados:
>>
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>
>> StmtText
>> |--Bookmark Lookup(BOOKMARK:([Bmk1000]),
>> OBJECT:([Documental].[dbo].[prueba]))
>> |--Index
>> Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
>> SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)
>>
>>
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>
>> StmtText
>> |--Clustered Index
>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>> WHERE:([prueba].[campo2]='Blanco'))
>>
>> Como veo aqui no usa el indice del campo, pero hace uso del indice de la
>> tabla, esto no va en contra del rendimiento???
>>
>> Hice una prueba mas y fue borrar el indice id_prueba_campo2
>>
>> drop index prueba.id_prueba_campo2
>> go
>>
>> y obtuve el mismo resultado que cuando lo tenia
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>
>> StmtText
>> |--Clustered Index
>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>> WHERE:([prueba].[campo2]='Blanco'))
>>
>> despues he borrado la pk
>>
>> alter table prueba drop constraint PK__prueba__20C1E124
>> go
>>
>> y obtuve el siguiente resultado
>>
>> StmtText
>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>
>> StmtText
>> |--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
>> WHERE:([prueba].[campo2]=[@1]))
>>
>> el cual tiene el mismo tiempo de respuesta como si hubiera tenido la pk
>> en
>> la tabla
>>
>> si bien lo que estoy buscando es como SQL Server puede diferenciar entre
>> una
>> cosa u otra, donde puedo encontrar infromación acerca de ello y poder
>> hacer
>> prueba, tambien considero que son pruebas aisladas pero pienso por lo
>> menos
>> que daran una idea de lo que podria hacer en una bd en produccion,
>> siguiendo
>> la misma tematica es donde podria tener informacion de como SQL Server
>> hace
>> uso de indices o no???? cosa que así se puede comprender mucho mas que es
>> bueno o malo y cuales son las mejores tecnicas que hay que aplicar.
>>
>> Espero no aburrirte con esto, es solo que la curiosidad es grande y el
>> hecho
>> de poder comparar hoy en día es una vemtaja pero para hacerlo hay que
>> conocer la herramienta que hace y que deja de hacer.
>>
>> Saludos
>>
>>
>>
>>
>> "Javier Loria" escribió en el mensaje
>> news:
>> > Hola:
>> > SQL 2000 y SQL 2005. No puedo probar con una 2000 pero debe tener el
>> > mismo comportamiento 2005.
>> > Lo que ves en que en tu caso, porque el codigo lo simplificaste
>> > "demasiado" el segundo indice se quedo como un "indice cubierto"
>> > (tiene
>> > todos los datos de la fila, ya que tienes todos los campos en el
>> > indice.
>> > Veamos que pasaria cuando agregas mas columnas:
>> > ==> >> > drop table prueba
>> >
>> > create table prueba(campo1 int primary key
>> > , campo2 varchar(100) NOT NULL
>> > , campo3 char(100) NOT NULL
>> > )
>> > go
>> > create index id_prueba_campo2 on prueba(campo2)
>> > go
>> > declare @i int
>> > set @i=0
>> > while @i <= 10000
>> > begin
>> > insert into prueba values(@i, 'Blanco', '')
>> > set @i=@i+1
>> > continue
>> > end
>> > go
>> > update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100, 1000,
>> > 10000, 100000, 1000000)
>> > go
>> >
>> > select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>> > uso el indice!!!
>> > select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>> > ==> >> > Espero se entienda.
>> > Saludos,
>> >
>> >
>> > Javier Loria
>> > Costa Rica (MVP)
>> > Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
>> > que pueda ser copiado y pegado al Query Analizer.
>> > La version de SQL y Service Pack tambien ayuda.
>> >
>> >
>> >
>> > "jcac" wrote in message
>> > news:
>> >> Hola Javier,
>> >>
>> >> Quizas me podrias indicar desde que versión SQL Server hace uso de
>> >> esto???, ya que hice una prueba, de este tipo
>> >>
>> >> create table prueba(campo1 int primary key, campo2 varchar(100))
>> >> go
>> >> create index id_prueba_campo2 on prueba(campo2)
>> >> go
>> >> declare @i int
>> >> set @i=0
>> >> while @i <= 1000000
>> >> begin
>> >> insert into prueba values(@i, 'Blanco')
>> >> continue
>> >> end
>> >> go
>> >> update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100,. 1000,
>> >> 10000, 100000, 1000000)
>> >> go
>> >>
>> >> ejecute esta dos consultas
>> >> select campo1, campo2 from prueba where campo2 = 'Negro'
>> >> teniendo un tiempo de respuesta muy rapido por menos del segundo,
>> >> adicionalmente vi el plan de ejecucionm y en definitiva hacia uso del
>> >> indice, luego lo hice con esta otra
>> >> select campo1, campo2 from prueba where campo2 = 'Blanco'
>> >> teniendo un tiempo de respuesta de aproximadamente unos 2 minutos y 28
>> >> segundos en su plan de ejecución vi que igualmente hacia uso del
>> >> indice.
>> >>
>> >> la versión de SQL Server que utilizo pra realizar esta prueba es la
>> >> MSDE
>> >> 2000 con SP4.
>> >>
>> >> Saludos
>> >>
>> >>
>> >> "Javier Loria" escribió en el mensaje
>> >> news:
>> >>> Hola:
>> >>> La forma en que se comporta SQL es mas o menos la que describiste.
>> >>> Si hay muchas filas que cumplen la igualdad no usara el indices y
>> >>> si
>> >>> hay pocas si.
>> >>> Por eso es importante hacer uso de indices con columns
>> >>> distintivas.
>> >>> Saludos,
>> >>>
>> >>> Javier Loria
>> >>> Costa Rica (MVP)
>> >>> Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
>> >>> que pueda ser copiado y pegado al Query Analizer.
>> >>> La version de SQL y Service Pack tambien ayuda.
>> >>>
>> >>> "jcac" wrote in message
>> >>> news:
>> >>>> Hola lista
>> >>>>
>> >>>> Ayer asisti a una presentacion de DB2, en la que indicaron que según
>> >>>> su
>> >>>> optimizador, que indican es inteligente, hace las siguientes
>> >>>> difenrencias por ejemplo:
>> >>>>
Respuesta Responder a este mensaje
#14 Alejandro Mesa
14/05/2007 - 16:54 | Informe spam
jcac,

Olvide postear un link muy interesante sobre el tema. No es muy nuevo que
digamos, pero toca puntos aun vigentes.

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/


AMB


"jcac" wrote:

Alejandro y Javier,

Les agradesco mucho lo que me han explicado en estos días por lo que
considero un conocimiento que han compartido que es invaluable.

Saludos

Juan Carlos


"Javier Loria" escribió en el mensaje
news:
> Hola Alejandro:
> Gracias...
> Saludos,
>
> Javier Loria
> Costa Rica (MVP)
> Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
> que pueda ser copiado y pegado al Query Analizer.
> La version de SQL y Service Pack tambien ayuda.
>
> "Alejandro Mesa" wrote in
> message news:
>> jcac,
>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>>
>>> StmtText
>>> |--Bookmark Lookup(BOOKMARK:([Bmk1000]),
>>> OBJECT:([Documental].[dbo].[prueba]))
>>> |--Index
>>> Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
>>> SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)
>>
>> Ya lo explique en otro e-mail. La tabla tiene un indice por [campo2] y
>> solo
>> 7 filas machan esa expresion (where campo2 = 'Negro'). El indice es
>> bastante
>> selectivo (pocas filas para una expresion en concreto) y por lo tanto es
>> menos costoso buscar en ese indice por [campo2], tomar el valor de la
>> clave
>> primaria e ir a buscar el resto de la data en el indice clustered. Esta
>> accion se llama "bookmark lookup". Exactamente con esta indicado en el
>> plan
>> de ejecucion.
>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>
>> Demasiadas filas machan esa expresion (where campo2 = 'Blanco'), asi que
>> en
>> vez de buscar en el indice nonclustered, por [campo2], y luego ir a
>> buscar el
>> resto de la data en el indice clustered (PK__prueba__20C1E124, y por
>> favor no
>> confundas indice con clave primaria), SQL Server decide que es menos
>> costoso
>> escanear el indice clustered y encontrar la data deseada. Tal como se ve
>> en
>> el plan de ejecucion, el indice nonclustered por [campo2] no es de ayuda
>> alguna.
>>
>>> drop index prueba.id_prueba_campo2
>>> go
>>>
>>> y obtuve el mismo resultado que cuando lo tenia
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>
>> Si borras el indice nonclustered, entonces solamente queda un solo lugar
>> donde buscar la data y es en el indice clustered (recuerda que los nodos
>> hojas de un indice clustered son las paginas de data).
>>
>>> alter table prueba drop constraint PK__prueba__20C1E124
>>> go
>>>
>>> y obtuve el siguiente resultado
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
>>> WHERE:([prueba].[campo2]=[@1]))
>>
>> Bueno, ya no tienes indice alguno, ahora solo queda la tabla sin indice
>> clustered (heap). Donde mas puede buscarse la data que escaneando la
>> propia
>> tabla. Si una tabla tiene indice clustered, entonces este sera usado. Si
>> la
>> tabla no tiene indice clustered, entonces la tabla sera usada.
>>
>>
>> AMB
>>
>>
>> "jcac" wrote:
>>
>>> Hola Javier,
>>>
>>> Muchas gracias por tu paciencia y disposición para ver este tema.
>>>
>>> Bueno hice la prueba para ver dicho comportamiento y aqui tengo los
>>> resultados:
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>>
>>> StmtText
>>> |--Bookmark Lookup(BOOKMARK:([Bmk1000]),
>>> OBJECT:([Documental].[dbo].[prueba]))
>>> |--Index
>>> Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
>>> SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)
>>>
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>>
>>> Como veo aqui no usa el indice del campo, pero hace uso del indice de la
>>> tabla, esto no va en contra del rendimiento???
>>>
>>> Hice una prueba mas y fue borrar el indice id_prueba_campo2
>>>
>>> drop index prueba.id_prueba_campo2
>>> go
>>>
>>> y obtuve el mismo resultado que cuando lo tenia
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>>
>>> despues he borrado la pk
>>>
>>> alter table prueba drop constraint PK__prueba__20C1E124
>>> go
>>>
>>> y obtuve el siguiente resultado
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
>>> WHERE:([prueba].[campo2]=[@1]))
>>>
>>> el cual tiene el mismo tiempo de respuesta como si hubiera tenido la pk
>>> en
>>> la tabla
>>>
>>> si bien lo que estoy buscando es como SQL Server puede diferenciar entre
>>> una
>>> cosa u otra, donde puedo encontrar infromación acerca de ello y poder
>>> hacer
>>> prueba, tambien considero que son pruebas aisladas pero pienso por lo
>>> menos
>>> que daran una idea de lo que podria hacer en una bd en produccion,
>>> siguiendo
>>> la misma tematica es donde podria tener informacion de como SQL Server
>>> hace
>>> uso de indices o no???? cosa que así se puede comprender mucho mas que
>>> es
>>> bueno o malo y cuales son las mejores tecnicas que hay que aplicar.
>>>
>>> Espero no aburrirte con esto, es solo que la curiosidad es grande y el
>>> hecho
>>> de poder comparar hoy en día es una vemtaja pero para hacerlo hay que
>>> conocer la herramienta que hace y que deja de hacer.
>>>
>>> Saludos
>>>
>>>
>>>
>>>
>>> "Javier Loria" escribió en el mensaje
>>> news:
>>> > Hola:
>>> > SQL 2000 y SQL 2005. No puedo probar con una 2000 pero debe tener
>>> > el
>>> > mismo comportamiento 2005.
>>> > Lo que ves en que en tu caso, porque el codigo lo simplificaste
>>> > "demasiado" el segundo indice se quedo como un "indice cubierto"
>>> > (tiene
>>> > todos los datos de la fila, ya que tienes todos los campos en el
>>> > indice.
>>> > Veamos que pasaria cuando agregas mas columnas:
>>> > ==> >>> > drop table prueba
>>> >
>>> > create table prueba(campo1 int primary key
>>> > , campo2 varchar(100) NOT NULL
>>> > , campo3 char(100) NOT NULL
>>> > )
>>> > go
>>> > create index id_prueba_campo2 on prueba(campo2)
>>> > go
>>> > declare @i int
>>> > set @i=0
>>> > while @i <= 10000
>>> > begin
>>> > insert into prueba values(@i, 'Blanco', '')
>>> > set @i=@i+1
>>> > continue
>>> > end
>>> > go
>>> > update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100, 1000,
>>> > 10000, 100000, 1000000)
>>> > go
>>> >
>>> > select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>> > sea
>>> > uso el indice!!!
>>> > select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>> > ==> >>> > Espero se entienda.
>>> > Saludos,
>>> >
>>> >
>>> > Javier Loria
>>> > Costa Rica (MVP)
>>> > Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
>>> > que pueda ser copiado y pegado al Query Analizer.
>>> > La version de SQL y Service Pack tambien ayuda.
>>> >
>>> >
>>> >
>>> > "jcac" wrote in message
>>> > news:
>>> >> Hola Javier,
>>> >>
>>> >> Quizas me podrias indicar desde que versión SQL Server hace uso de
>>> >> esto???, ya que hice una prueba, de este tipo
>>> >>
>>> >> create table prueba(campo1 int primary key, campo2 varchar(100))
>>> >> go
>>> >> create index id_prueba_campo2 on prueba(campo2)
>>> >> go
>>> >> declare @i int
>>> >> set @i=0
>>> >> while @i <= 1000000
>>> >> begin
>>> >> insert into prueba values(@i, 'Blanco')
>>> >> continue
>>> >> end
>>> >> go
>>> >> update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100,.
>>> >> 1000,
>>> >> 10000, 100000, 1000000)
>>> >> go
>>> >>
>>> >> ejecute esta dos consultas
>>> >> select campo1, campo2 from prueba where campo2 = 'Negro'
>>> >> teniendo un tiempo de respuesta muy rapido por menos del segundo,
>>> >> adicionalmente vi el plan de ejecucionm y en definitiva hacia uso del
>>> >> indice, luego lo hice con esta otra
>>> >> select campo1, campo2 from prueba where campo2 = 'Blanco'
>>> >> teniendo un tiempo de respuesta de aproximadamente unos 2 minutos y
>>> >> 28
>>> >> segundos en su plan de ejecución vi que igualmente hacia uso del
>>> >> indice.
>>> >>
>>> >> la versión de SQL Server que utilizo pra realizar esta prueba es la
>>> >> MSDE
>>> >> 2000 con SP4.
>>> >>
>>> >> Saludos
>>> >>
>>> >>
>>> >> "Javier Loria" escribió en el mensaje
>>> >> news:
>>> >>> Hola:
>>> >>> La forma en que se comporta SQL es mas o menos la que
>>> >>> describiste.
>>> >>> Si hay muchas filas que cumplen la igualdad no usara el indices y
>>> >>> si
>>> >>> hay pocas si.
>>> >>> Por eso es importante hacer uso de indices con columns
Respuesta Responder a este mensaje
#15 jcac
14/05/2007 - 19:57 | Informe spam
Alejandro,

Muchas gracias por el link.

Saludos

Juan Carlos


"Alejandro Mesa" escribió en el
mensaje news:
jcac,

Olvide postear un link muy interesante sobre el tema. No es muy nuevo que
digamos, pero toca puntos aun vigentes.

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/


AMB


"jcac" wrote:

Alejandro y Javier,

Les agradesco mucho lo que me han explicado en estos días por lo que
considero un conocimiento que han compartido que es invaluable.

Saludos

Juan Carlos


"Javier Loria" escribió en el mensaje
news:
> Hola Alejandro:
> Gracias...
> Saludos,
>
> Javier Loria
> Costa Rica (MVP)
> Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
> que pueda ser copiado y pegado al Query Analizer.
> La version de SQL y Service Pack tambien ayuda.
>
> "Alejandro Mesa" wrote in
> message news:
>> jcac,
>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>>
>>> StmtText
>>> |--Bookmark Lookup(BOOKMARK:([Bmk1000]),
>>> OBJECT:([Documental].[dbo].[prueba]))
>>> |--Index
>>> Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
>>> SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)
>>
>> Ya lo explique en otro e-mail. La tabla tiene un indice por [campo2] y
>> solo
>> 7 filas machan esa expresion (where campo2 = 'Negro'). El indice es
>> bastante
>> selectivo (pocas filas para una expresion en concreto) y por lo tanto
>> es
>> menos costoso buscar en ese indice por [campo2], tomar el valor de la
>> clave
>> primaria e ir a buscar el resto de la data en el indice clustered.
>> Esta
>> accion se llama "bookmark lookup". Exactamente con esta indicado en el
>> plan
>> de ejecucion.
>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>
>> Demasiadas filas machan esa expresion (where campo2 = 'Blanco'), asi
>> que
>> en
>> vez de buscar en el indice nonclustered, por [campo2], y luego ir a
>> buscar el
>> resto de la data en el indice clustered (PK__prueba__20C1E124, y por
>> favor no
>> confundas indice con clave primaria), SQL Server decide que es menos
>> costoso
>> escanear el indice clustered y encontrar la data deseada. Tal como se
>> ve
>> en
>> el plan de ejecucion, el indice nonclustered por [campo2] no es de
>> ayuda
>> alguna.
>>
>>> drop index prueba.id_prueba_campo2
>>> go
>>>
>>> y obtuve el mismo resultado que cuando lo tenia
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>
>> Si borras el indice nonclustered, entonces solamente queda un solo
>> lugar
>> donde buscar la data y es en el indice clustered (recuerda que los
>> nodos
>> hojas de un indice clustered son las paginas de data).
>>
>>> alter table prueba drop constraint PK__prueba__20C1E124
>>> go
>>>
>>> y obtuve el siguiente resultado
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
>>> WHERE:([prueba].[campo2]=[@1]))
>>
>> Bueno, ya no tienes indice alguno, ahora solo queda la tabla sin
>> indice
>> clustered (heap). Donde mas puede buscarse la data que escaneando la
>> propia
>> tabla. Si una tabla tiene indice clustered, entonces este sera usado.
>> Si
>> la
>> tabla no tiene indice clustered, entonces la tabla sera usada.
>>
>>
>> AMB
>>
>>
>> "jcac" wrote:
>>
>>> Hola Javier,
>>>
>>> Muchas gracias por tu paciencia y disposición para ver este tema.
>>>
>>> Bueno hice la prueba para ver dicho comportamiento y aqui tengo los
>>> resultados:
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>>
>>> StmtText
>>> |--Bookmark Lookup(BOOKMARK:([Bmk1000]),
>>> OBJECT:([Documental].[dbo].[prueba]))
>>> |--Index
>>> Seek(OBJECT:([Documental].[dbo].[prueba].[id_prueba_campo2]),
>>> SEEK:([prueba].[campo2]='Negro') ORDERED FORWARD)
>>>
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>>
>>> Como veo aqui no usa el indice del campo, pero hace uso del indice de
>>> la
>>> tabla, esto no va en contra del rendimiento???
>>>
>>> Hice una prueba mas y fue borrar el indice id_prueba_campo2
>>>
>>> drop index prueba.id_prueba_campo2
>>> go
>>>
>>> y obtuve el mismo resultado que cuando lo tenia
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Clustered Index
>>> Scan(OBJECT:([Documental].[dbo].[prueba].[PK__prueba__20C1E124]),
>>> WHERE:([prueba].[campo2]='Blanco'))
>>>
>>> despues he borrado la pk
>>>
>>> alter table prueba drop constraint PK__prueba__20C1E124
>>> go
>>>
>>> y obtuve el siguiente resultado
>>>
>>> StmtText
>>> select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>>
>>> StmtText
>>> |--Table Scan(OBJECT:([Documental].[dbo].[prueba]),
>>> WHERE:([prueba].[campo2]=[@1]))
>>>
>>> el cual tiene el mismo tiempo de respuesta como si hubiera tenido la
>>> pk
>>> en
>>> la tabla
>>>
>>> si bien lo que estoy buscando es como SQL Server puede diferenciar
>>> entre
>>> una
>>> cosa u otra, donde puedo encontrar infromación acerca de ello y poder
>>> hacer
>>> prueba, tambien considero que son pruebas aisladas pero pienso por lo
>>> menos
>>> que daran una idea de lo que podria hacer en una bd en produccion,
>>> siguiendo
>>> la misma tematica es donde podria tener informacion de como SQL
>>> Server
>>> hace
>>> uso de indices o no???? cosa que así se puede comprender mucho mas
>>> que
>>> es
>>> bueno o malo y cuales son las mejores tecnicas que hay que aplicar.
>>>
>>> Espero no aburrirte con esto, es solo que la curiosidad es grande y
>>> el
>>> hecho
>>> de poder comparar hoy en día es una vemtaja pero para hacerlo hay que
>>> conocer la herramienta que hace y que deja de hacer.
>>>
>>> Saludos
>>>
>>>
>>>
>>>
>>> "Javier Loria" escribió en el mensaje
>>> news:
>>> > Hola:
>>> > SQL 2000 y SQL 2005. No puedo probar con una 2000 pero debe
>>> > tener
>>> > el
>>> > mismo comportamiento 2005.
>>> > Lo que ves en que en tu caso, porque el codigo lo simplificaste
>>> > "demasiado" el segundo indice se quedo como un "indice cubierto"
>>> > (tiene
>>> > todos los datos de la fila, ya que tienes todos los campos en el
>>> > indice.
>>> > Veamos que pasaria cuando agregas mas columnas:
>>> > ==>> >>> > drop table prueba
>>> >
>>> > create table prueba(campo1 int primary key
>>> > , campo2 varchar(100) NOT NULL
>>> > , campo3 char(100) NOT NULL
>>> > )
>>> > go
>>> > create index id_prueba_campo2 on prueba(campo2)
>>> > go
>>> > declare @i int
>>> > set @i=0
>>> > while @i <= 10000
>>> > begin
>>> > insert into prueba values(@i, 'Blanco', '')
>>> > set @i=@i+1
>>> > continue
>>> > end
>>> > go
>>> > update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100,
>>> > 1000,
>>> > 10000, 100000, 1000000)
>>> > go
>>> >
>>> > select campo1, campo2, campo3 from prueba where campo2 = 'Negro'
>>> > sea
>>> > uso el indice!!!
>>> > select campo1, campo2, campo3 from prueba where campo2 = 'Blanco'
>>> > ==>> >>> > Espero se entienda.
>>> > Saludos,
>>> >
>>> >
>>> > Javier Loria
>>> > Costa Rica (MVP)
>>> > Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
>>> > que pueda ser copiado y pegado al Query Analizer.
>>> > La version de SQL y Service Pack tambien ayuda.
>>> >
>>> >
>>> >
>>> > "jcac" wrote in message
>>> > news:
>>> >> Hola Javier,
>>> >>
>>> >> Quizas me podrias indicar desde que versión SQL Server hace uso de
>>> >> esto???, ya que hice una prueba, de este tipo
>>> >>
>>> >> create table prueba(campo1 int primary key, campo2 varchar(100))
>>> >> go
>>> >> create index id_prueba_campo2 on prueba(campo2)
>>> >> go
>>> >> declare @i int
>>> >> set @i=0
>>> >> while @i <= 1000000
>>> >> begin
>>> >> insert into prueba values(@i, 'Blanco')
>>> >> continue
>>> >> end
>>> >> go
>>> >> update prueba set campo2 = 'Negro' where campo1 in (1, 10, 100,.
>>> >> 1000,
>>> >> 10000, 100000, 1000000)
>>> >> go
>>> >>
>>> >> ejecute esta dos consultas
>>> >> select campo1, campo2 from prueba where campo2 = 'Negro'
>>> >> teniendo un tiempo de respuesta muy rapido por menos del segundo,
>>> >> adicionalmente vi el plan de ejecucionm y en definitiva hacia uso
>>> >> del
>>> >> indice, luego lo hice con esta otra
>>> >> select campo1, campo2 from prueba where campo2 = 'Blanco'
>>> >> teniendo un tiempo de respuesta de aproximadamente unos 2 minutos
>>> >> y
>>> >> 28
>>> >> segundos en su plan de ejecución vi que igualmente hacia uso del
>>> >> indice.
>>> >>
>>> >> la versión de SQL Server que utilizo pra realizar esta prueba es
>>> >> la
>>> >> MSDE
>>> >> 2000 con SP4.
>>> >>
>>> >> Saludos
>>> >>
>>> >>
>>> >> "Javier Loria" escribió en el mensaje
>>> >> news:
>>> >>> Hola:
>>> >>> La forma en que se comporta SQL es mas o menos la que
>>> >>> describiste.
>>> >>> Si hay muchas filas que cumplen la igualdad no usara el
>>> >>> indices y
>>> >>> si
>>> >>> hay pocas si.
>>> >>> Por eso es importante hacer uso de indices con columns
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida