La regla de la izquierda -- Indices

04/02/2009 - 08:16 por Normanmp | Informe spam
La regla de la izquierda -> Sé que esto funciona para MYSQL tengo dudas si es
tambien valido para SQL server, por lo que megustaria que me lo confirmarais:

Supongamos un INDEX usuario (id, name, adress), y una cláusula SELECT ...
WHERE NAME = x. Este Select no aprovechará el índice. Tampoco lo haría un
SELECT ... WHERE ID =X AND ADRESS = Y. Cualquier consulta que incluya una
columna parte del index sin incluir además las columnas a su izquierda, no
usará el indice.

Por tanto en nuestro ejemplo solo sacarian provecho del indice las consultas
SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x AND NAME
= y AND ADRESS = Z

Gracias

Preguntas similare

Leer las respuestas

#6 Alejandro Mesa
06/02/2009 - 19:25 | Informe spam
Jose Mariano Alvarez,

Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
supongamos en extremo 1 registro



Eso lo sabes tu, pero SQL Server no tiene idea de cuantos registros cumplen
esa condicion en ese indice puesto que no hay estadisticas para saberlo y no
va a tomar el riesgo de scanear el indice para luego hacer key lookup.

Puedo estar equivocado, puesto que en cada version el codigo de l
optimizador de queries es mejorado.

Te propongo hagas una prueba a ver si logras lo que dices.


AMB



"Jose Mariano Alvarez" wrote:

Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
supongamos en extremo 1 registro, y si la cantidad de paginas de la tabla es
grande en comparacion al indice, va a hacer un index scan y luego el lookup
ya que eso es menos costoso que el scan de la table. Si la cantidad de
registros crece, va a llegar un punto que el costo que produce la estructura
de los indices y la aleatorizacion de accesos del nonclustered index que va
a preferir un acceso mediante un table scan.


Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase. Por
favor tratar 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.










"Alejandro Mesa" wrote in message
news:
> Corrección:
>
>> no asi para:
>>
>> ...
>> where c3 = ?
>>
>> en cuyo caso puede usarse el valor de "All density" ligado a esa columna,
>> pero este valor no es tan exacto como el de la distribucion de el
>> histograma.
>
> Me contradije enesta declaracion, pues no existe valor de "All Density"
> solo
> para esa columna. La combinacion es progresiva empezando desde la
> izquierda y
> debe incluir las columnas previas. Por eso no es posible estimar el numero
> de
> filas que pueden machar la expresion:
>
> ...
> where c3 = ?
>
> y por lo tanto se debera hacer un scan de la tabla o el indice clustered
> en
> caso de este existir.
>
>
> AMB
>
>
> "Alejandro Mesa" wrote:
>
>> Normanmp,
>>
>> SQL Server mantiene estadisticas de distribución de los valores presentes
>> en
>> las columnas que forman parte de un indice, pero el histograma de
>> distribucion se mantiene solo para la columna lider o primera de
>> izquierda a
>> derecha en la definicion de la llave. Entre otras estadisticas, tambien
>> se
>> tiene un valor llamado "All density" de la combinacion de columnas de
>> izquirda a derecha, incluyendo tambien las columnas de el indice
>> clustered en
>> caso de existir.
>>
>> create clustered index _t_c1_nu_c_ix
>> on dbo.t(c1)
>>
>> create nonclustered index t_c2_c3_nu_nc_ix
>> on dbo.t(c2, c3)
>>
>> All Density (para el indice nonclustered)
>>
>> c2 -- x1
>> c2, c3 -- x2
>> c2, c3, c1 -- x3
>>
>> Las estadisticas de distribucion, se utilizan principalmente para estimar
>> el
>> numero de filas que pueden machar cierto predicado, y como el histograma
>> solo
>> se mantiene para la columna lider de la clave, entonces esta se debe usar
>> en
>> el predicado para poder tener acceso a este.
>>
>> Basado en el indice nonclustered anterior, tenemos acceso a su histograma
>> si
>> usamos:
>>
>> ...
>> where c2 = ?
>>
>> ...
>> where c2 = ? and c3 = ?
>>
>> no asi para:
>>
>> ...
>> where c3 = ?
>>
>> en cuyo caso puede usarse el valor de "All density" ligado a esa columna,
>> pero este valor no es tan exacto como el de la distribucion de el
>> histograma.
>>
>> Te recomiendo la lectura de el comando DBCC SHOW_STATISTICS en los BOL.
>>
>> Aqui te paso un par de link que te pudieran ser de ayuda. Estos articulos
>> estan basado en SS 2000, pero la mayoria de lo que se explica aplica a
>> 2005.
>>
>> Estadísticas de distribución en SQL Server 2000 (I)
>> http://www.helpdna.net/sqlserver_20...ndices.htm
>>
>> Estadísticas de Distribución en SQL Server 2000 (2)
>> http://www.configuracionesintegrale...articulo34
>>
>>
>> AMB
>>
>>
>> "Normanmp" wrote:
>>
>> > La regla de la izquierda -> Sé que esto funciona para MYSQL tengo dudas
>> > si es
>> > tambien valido para SQL server, por lo que megustaria que me lo
>> > confirmarais:
>> >
>> > Supongamos un INDEX usuario (id, name, adress), y una cláusula SELECT
>> > ...
>> > WHERE NAME = x. Este Select no aprovechará el índice. Tampoco lo haría
>> > un
>> > SELECT ... WHERE ID =X AND ADRESS = Y. Cualquier consulta que incluya
>> > una
>> > columna parte del index sin incluir además las columnas a su izquierda,
>> > no
>> > usará el indice.
>> >
>> > Por tanto en nuestro ejemplo solo sacarian provecho del indice las
>> > consultas
>> > SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x AND
>> > NAME
>> > = y AND ADRESS = Z
>> >
>> > Gracias
>> >
Respuesta Responder a este mensaje
#7 Jose Mariano Alvarez
08/02/2009 - 13:12 | Informe spam
Va el ejemplo de lo que dije.
Lo probe en 2000. 2005 y 2008
Espero sirva




use prueba
go



SET NOCOUNT ON
GO


SET STATISTICS PROFILE OFF
go



CREATE TABLE dbo.POC_CoverIndex(
A smallint NOT NULL,
B smallint NOT NULL,
C int NOT NULL,
descrip char(255) NOT NULL
)
GO
ALTER TABLE dbo.POC_CoverIndex
ADD CONSTRAINT PK_POC_CoverIndex PRIMARY KEY NONCLUSTERED (
A,B,C
)
GO



declare @I int
set @i= 10000

While @i > 0
begin
insert into dbo.POC_CoverIndex
values(@i/10000,@i%1000,@i,convert(char(255),@i))
set @i = @i -1
end










if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8'
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
else
select * from sys.indexes where object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )



if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8' --
SQL Server 2000
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and
name like '_WA_Sys%'
else
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





SET STATISTICS PROFILE ON



Select * from dbo.POC_CoverIndex where c = 500




SET STATISTICS PROFILE OFF




if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8'
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
else
select * from sys.indexes where object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8' --
SQL Server 2000
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and
name like '_WA_Sys%'
else
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





declare @StatName varchar(255)
if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8' --
SQL Server 2000
SELECT @StatName = name
from sysindexes
where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and name like '_WA_Sys%'
else
SELECT @StatName = name
FROM sys.stats
WHERE object_id = OBJECT_ID ('dbo.POC_CoverIndex' ) and auto_created = 1
dbcc show_statistics('dbo.POC_CoverIndex', @StatName )








DROP TABLE dbo.POC_CoverIndex
GO






Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase. Por
favor tratar 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.










"Alejandro Mesa" wrote in message
news:
Jose Mariano Alvarez,

Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
supongamos en extremo 1 registro



Eso lo sabes tu, pero SQL Server no tiene idea de cuantos registros
cumplen
esa condicion en ese indice puesto que no hay estadisticas para saberlo y
no
va a tomar el riesgo de scanear el indice para luego hacer key lookup.

Puedo estar equivocado, puesto que en cada version el codigo de l
optimizador de queries es mejorado.

Te propongo hagas una prueba a ver si logras lo que dices.


AMB



"Jose Mariano Alvarez" wrote:

Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
supongamos en extremo 1 registro, y si la cantidad de paginas de la tabla
es
grande en comparacion al indice, va a hacer un index scan y luego el
lookup
ya que eso es menos costoso que el scan de la table. Si la cantidad de
registros crece, va a llegar un punto que el costo que produce la
estructura
de los indices y la aleatorizacion de accesos del nonclustered index que
va
a preferir un acceso mediante un table scan.


Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase.
Por
favor tratar 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.










"Alejandro Mesa" wrote in
message
news:
> Corrección:
>
>> no asi para:
>>
>> ...
>> where c3 = ?
>>
>> en cuyo caso puede usarse el valor de "All density" ligado a esa
>> columna,
>> pero este valor no es tan exacto como el de la distribucion de el
>> histograma.
>
> Me contradije enesta declaracion, pues no existe valor de "All Density"
> solo
> para esa columna. La combinacion es progresiva empezando desde la
> izquierda y
> debe incluir las columnas previas. Por eso no es posible estimar el
> numero
> de
> filas que pueden machar la expresion:
>
> ...
> where c3 = ?
>
> y por lo tanto se debera hacer un scan de la tabla o el indice
> clustered
> en
> caso de este existir.
>
>
> AMB
>
>
> "Alejandro Mesa" wrote:
>
>> Normanmp,
>>
>> SQL Server mantiene estadisticas de distribución de los valores
>> presentes
>> en
>> las columnas que forman parte de un indice, pero el histograma de
>> distribucion se mantiene solo para la columna lider o primera de
>> izquierda a
>> derecha en la definicion de la llave. Entre otras estadisticas,
>> tambien
>> se
>> tiene un valor llamado "All density" de la combinacion de columnas de
>> izquirda a derecha, incluyendo tambien las columnas de el indice
>> clustered en
>> caso de existir.
>>
>> create clustered index _t_c1_nu_c_ix
>> on dbo.t(c1)
>>
>> create nonclustered index t_c2_c3_nu_nc_ix
>> on dbo.t(c2, c3)
>>
>> All Density (para el indice nonclustered)
>>
>> c2 -- x1
>> c2, c3 -- x2
>> c2, c3, c1 -- x3
>>
>> Las estadisticas de distribucion, se utilizan principalmente para
>> estimar
>> el
>> numero de filas que pueden machar cierto predicado, y como el
>> histograma
>> solo
>> se mantiene para la columna lider de la clave, entonces esta se debe
>> usar
>> en
>> el predicado para poder tener acceso a este.
>>
>> Basado en el indice nonclustered anterior, tenemos acceso a su
>> histograma
>> si
>> usamos:
>>
>> ...
>> where c2 = ?
>>
>> ...
>> where c2 = ? and c3 = ?
>>
>> no asi para:
>>
>> ...
>> where c3 = ?
>>
>> en cuyo caso puede usarse el valor de "All density" ligado a esa
>> columna,
>> pero este valor no es tan exacto como el de la distribucion de el
>> histograma.
>>
>> Te recomiendo la lectura de el comando DBCC SHOW_STATISTICS en los
>> BOL.
>>
>> Aqui te paso un par de link que te pudieran ser de ayuda. Estos
>> articulos
>> estan basado en SS 2000, pero la mayoria de lo que se explica aplica a
>> 2005.
>>
>> Estadísticas de distribución en SQL Server 2000 (I)
>> http://www.helpdna.net/sqlserver_20...ndices.htm
>>
>> Estadísticas de Distribución en SQL Server 2000 (2)
>> http://www.configuracionesintegrale...articulo34
>>
>>
>> AMB
>>
>>
>> "Normanmp" wrote:
>>
>> > La regla de la izquierda -> Sé que esto funciona para MYSQL tengo
>> > dudas
>> > si es
>> > tambien valido para SQL server, por lo que megustaria que me lo
>> > confirmarais:
>> >
>> > Supongamos un INDEX usuario (id, name, adress), y una cláusula
>> > SELECT
>> > ...
>> > WHERE NAME = x. Este Select no aprovechará el índice. Tampoco lo
>> > haría
>> > un
>> > SELECT ... WHERE ID =X AND ADRESS = Y. Cualquier consulta que
>> > incluya
>> > una
>> > columna parte del index sin incluir además las columnas a su
>> > izquierda,
>> > no
>> > usará el indice.
>> >
>> > Por tanto en nuestro ejemplo solo sacarian provecho del indice las
>> > consultas
>> > SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x
>> > AND
>> > NAME
>> > = y AND ADRESS = Z
>> >
>> > Gracias
>> >
Respuesta Responder a este mensaje
#8 Alejandro Mesa
08/02/2009 - 18:53 | Informe spam
Jose Mariano Alvarez,

Creo que tienes una confución aqui, o quizas sea yo quien la tenga, asi que
vamos a tratar de averiguar como el optimizador determino que solo una fila
macha esa expresion.

Logicamente queel optimizador no saco esta conclusión de las estadisticas
normales de ese indice, pues como ya comente anteriormente, tenemos
estadiscas sobre la distribucion de valores de la columna lider, en este caso
A, y tenemos valores de densidad para la combinacion de columnas de el
indice, combinacion de izquierda a derecha (A), (A, B), (A, B, C).

DBCC SHOW_STATISTICS ('dbo.POC_CoverIndex', 'PK_POC_CoverIndex');
GO

Entonces de donde saco el optimizador el valor estimado de el numero de
filas que cumplen la expresion?

Bueno, si la base de datos tiene prendida la opción
"AUTO_CREATE_STATISTICS", la cual por lo general debe estar prendida,
entonces al analizar la consulta, este crea una estadistica para la columna
C, pues no existe un indice que nos pueda proveer estadisticas sobre esta
columna por si sola. Al ver que solo una fila macha esta expresion, entonces
decide scanear el indice nonclustered, que es mucho mas estrecho que la
tabla, pues solo contiene informacion sobre A, B, C y luego hace un lookup en
la tabla para traer el valor de la columna [descrip]. Este plan es mucho
menos costoso que leer toda la tabla para encontrar la fila que macha con esa
expresion, porque este puede estar al final de la tabla.

Como podemos probar lo dicho?

1 - Apagamos la opcion AUTO_CREATE_STATISTICS en la db donde se hace la
prueba. Esto antes de ejecutar ela sentencia select.

ALTER DATABASE prueba
SET AUTO_CREATE_STATISTICS OFF;
GO

2 - Para ser justo, actualizamos las estadisticas de el indice despues de
cargar la tabla.

UPDATE STATISTICS dbo.POC_CoverIndex WITH FULLSCAN;
GO

3 - Ejecuta la senetencia select cuantas veces sea necesario, hasta que
estemos convencidos de lo que vemos, que es el scan de la tabla, pues no
tenemos estadisticas para determinar las filas que machan esa expresion.

4 - Prende la opcion, o en su lugar crea la estadistica a mano.


ALTER DATABASE prueba
SET AUTO_CREATE_STATISTICS ON;
GO


CREATE STATISTICS POC_CoverIndex_C
ON dbo.POC_CoverIndex(C) WITH FULLSCAN;
GO

5 - Limpia el cache de procedimientos por si acaso.

DBCC freeproccache;
GO

Fijate que tu mismo comentas sobre la estadistica generada automaticamente
sobre la columna C, en tu codigo de ejemplo. Pero eso no quiere decir que el
optimizador puso esa estadistica en el indice, sino que creo una nueva para
poder estimar expresiones sobre esa columna y la crea justo por eso, porque
no tenia de donde sacar numero alguno para estimar la cardinalidad de la
expresion.

Si miramos las estadisticas almacenadas en esta nueva estadistica que se
creo (valga aqui la redondancia):

DBCC SHOW_STATISTICS ('dbo.POC_CoverIndex', 'POC_CoverIndex_C');
GO

Vemos que la segunda fila en el histograma, dice que hay 9,997 filas en el
rango > 1 y <= 9999, que una fila tiene el valor de la columna C = 9999 y que
9997 de el resto de los valores son unicos. Por lo que podemos estimar que
solo una fila cumple la expresion C = 500.


Vuelvo a repetir, si el indice que tenemos es (A, B, C), en este caso
nonclustered, y ademas no tenemos indice clustered, y la expresion en el
predicado es:

...
where B = ?

ó

...
where C = ?
entonces SQL Server no

entonces el optimizador no tiene de donde estimar el numero de filas que
pueden machar esa expresion. Es por eso que es importante tener prendida la
opcion AUTO_CREATE_STATISTICS para que nuevas estadisticas se generen cuando
estas hagan falta. Tambien es importante tener prendida la opcion
AUTO_UPDATE_STATISTICS para que estas estadisticas se actualizen a medida que
insertamos nuevas filas o actualizamos o borramos filas existentes.



AMB



"Jose Mariano Alvarez" wrote:

Va el ejemplo de lo que dije.
Lo probe en 2000. 2005 y 2008
Espero sirva




use prueba
go



SET NOCOUNT ON
GO


SET STATISTICS PROFILE OFF
go



CREATE TABLE dbo.POC_CoverIndex(
A smallint NOT NULL,
B smallint NOT NULL,
C int NOT NULL,
descrip char(255) NOT NULL
)
GO
ALTER TABLE dbo.POC_CoverIndex
ADD CONSTRAINT PK_POC_CoverIndex PRIMARY KEY NONCLUSTERED (
A,B,C
)
GO



declare @I int
set @i= 10000

While @i > 0
begin
insert into dbo.POC_CoverIndex
values(@i/10000,@i%1000,@i,convert(char(255),@i))
set @i = @i -1
end










if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8'
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
else
select * from sys.indexes where object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )



if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8' --
SQL Server 2000
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and
name like '_WA_Sys%'
else
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





SET STATISTICS PROFILE ON



Select * from dbo.POC_CoverIndex where c = 500




SET STATISTICS PROFILE OFF




if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8'
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
else
select * from sys.indexes where object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8' --
SQL Server 2000
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and
name like '_WA_Sys%'
else
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





declare @StatName varchar(255)
if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) =
'8' --
SQL Server 2000
SELECT @StatName = name
from sysindexes
where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and name like '_WA_Sys%'
else
SELECT @StatName = name
FROM sys.stats
WHERE object_id = OBJECT_ID ('dbo.POC_CoverIndex' ) and auto_created = 1
dbcc show_statistics('dbo.POC_CoverIndex', @StatName )








DROP TABLE dbo.POC_CoverIndex
GO






Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase. Por
favor tratar 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.










"Alejandro Mesa" wrote in message
news:
> Jose Mariano Alvarez,
>
>> Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
>> supongamos en extremo 1 registro
>
> Eso lo sabes tu, pero SQL Server no tiene idea de cuantos registros
> cumplen
> esa condicion en ese indice puesto que no hay estadisticas para saberlo y
> no
> va a tomar el riesgo de scanear el indice para luego hacer key lookup.
>
> Puedo estar equivocado, puesto que en cada version el codigo de l
> optimizador de queries es mejorado.
>
> Te propongo hagas una prueba a ver si logras lo que dices.
>
>
> AMB
>
>
>
> "Jose Mariano Alvarez" wrote:
>
>> Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
>> supongamos en extremo 1 registro, y si la cantidad de paginas de la tabla
>> es
>> grande en comparacion al indice, va a hacer un index scan y luego el
>> lookup
>> ya que eso es menos costoso que el scan de la table. Si la cantidad de
>> registros crece, va a llegar un punto que el costo que produce la
>> estructura
>> de los indices y la aleatorizacion de accesos del nonclustered index que
>> va
>> a preferir un acceso mediante un table scan.
>>
>>
>> Saludos
>>
>>
>> Ing. Jose Mariano Alvarez
>> SQLTotal Consulting
>>
>> (Cambia los ceros por O y saca lo que sobra)
>>
>> Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase.
>> Por
>> favor tratar 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.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> "Alejandro Mesa" wrote in
>> message
>> news:
>> > Corrección:
>> >
>> >> no asi para:
>> >>
>> >> ...
>> >> where c3 = ?
>> >>
>> >> en cuyo caso puede usarse el valor de "All density" ligado a esa
>> >> columna,
>> >> pero este valor no es tan exacto como el de la distribucion de el
>> >> histograma.
>> >
>> > Me contradije enesta declaracion, pues no existe valor de "All Density"
>> > solo
>> > para esa columna. La combinacion es progresiva empezando desde la
>> > izquierda y
>> > debe incluir las columnas previas. Por eso no es posible estimar el
>> > numero
>> > de
>> > filas que pueden machar la expresion:
>> >
>> > ...
>> > where c3 = ?
>> >
>> > y por lo tanto se debera hacer un scan de la tabla o el indice
>> > clustered
Respuesta Responder a este mensaje
#9 Jose Mariano Alvarez
09/02/2009 - 23:46 | Informe spam
Alejandro, pues creo que la confusion es semantica ya que lo que exprese
coincide con lo que sucede y ademas es totalmente consistente con tu
razonamiento y con el mio. Simplemente nunca dije que la estadistica se
agregaba al indice sino que podia usar el indice como "cover index" haciendo
un INDEX SCAN sobre el mismo.

Simplemente creo que me mal-interpretaste:

La pregunta original fue:
Por tanto en nuestro ejemplo solo sacarian provecho del indice las consultas
SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x AND NAME
= y AND ADRESS = Z

En tu correo donde te autocorregias expresaste
y por lo tanto se debera hacer un scan de la tabla o el indice clustered en
caso de este existir.

Lo cual a mi criterio no es correcto ya que no es lo que sucede Esto lo
exprese en mi correo y queria que se hiciera notar ya que no se si MySql lo
puede aprovechar de la misma manera que SQL Server

Lo que exprese fue:
Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
supongamos en extremo 1 registro, y si la cantidad de paginas de la tabla es
grande en comparacion al indice, va a hacer un index scan y luego el lookup
ya que eso es menos costoso que el scan de la table. Si la cantidad de
registros crece, va a llegar un punto que el costo que produce la estructura
de los indices y la aleatorizacion de accesos del nonclustered index que va
a preferir un acceso mediante un table scan.

Nunca exprese que haria un INDEX SEEK para obtener 1 registro sino que
implicitamente asumi que el SQL Server sabe que hay un solo registro. Aqui
omiti expresar lo de las estadisticas generadas automaticamente asi como que
me estaba refiriendo a un nonclustered index..

Tu me respondiste
Eso lo sabes tu, pero SQL Server no tiene idea de cuantos registros cumplen
esa condicion en ese indice puesto que no hay estadisticas para saberlo y no
va a tomar el riesgo de scanear el indice para luego hacer key lookup

Por eso envie el ejemplo que no coincide con esta frase.
Luego si exprese lo de las estadisticas en mi correo del ejemplo y tu lo
reflejas en tu ultimo correo.

Por lo tanto
IMPORTANTE
***********************************************************************
La respuesta exacta es NO, otras consultas
tambien pueden sacar provecho del indice
aun sin usar la regla de la izquierda.
***********************************************************************

Creo que coincidimos luego de agregar los detalles que faltaban en las
frases.
Espero que les sirva a quienes lo leen ya que creo es bastante rico como
ejemplo..



Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase. Por
favor tratar 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.










"Alejandro Mesa" wrote in message
news:
Jose Mariano Alvarez,

Creo que tienes una confución aqui, o quizas sea yo quien la tenga, asi
que
vamos a tratar de averiguar como el optimizador determino que solo una
fila
macha esa expresion.

Logicamente queel optimizador no saco esta conclusión de las estadisticas
normales de ese indice, pues como ya comente anteriormente, tenemos
estadiscas sobre la distribucion de valores de la columna lider, en este
caso
A, y tenemos valores de densidad para la combinacion de columnas de el
indice, combinacion de izquierda a derecha (A), (A, B), (A, B, C).

DBCC SHOW_STATISTICS ('dbo.POC_CoverIndex', 'PK_POC_CoverIndex');
GO

Entonces de donde saco el optimizador el valor estimado de el numero de
filas que cumplen la expresion?

Bueno, si la base de datos tiene prendida la opción
"AUTO_CREATE_STATISTICS", la cual por lo general debe estar prendida,
entonces al analizar la consulta, este crea una estadistica para la
columna
C, pues no existe un indice que nos pueda proveer estadisticas sobre esta
columna por si sola. Al ver que solo una fila macha esta expresion,
entonces
decide scanear el indice nonclustered, que es mucho mas estrecho que la
tabla, pues solo contiene informacion sobre A, B, C y luego hace un lookup
en
la tabla para traer el valor de la columna [descrip]. Este plan es mucho
menos costoso que leer toda la tabla para encontrar la fila que macha con
esa
expresion, porque este puede estar al final de la tabla.

Como podemos probar lo dicho?

1 - Apagamos la opcion AUTO_CREATE_STATISTICS en la db donde se hace la
prueba. Esto antes de ejecutar ela sentencia select.

ALTER DATABASE prueba
SET AUTO_CREATE_STATISTICS OFF;
GO

2 - Para ser justo, actualizamos las estadisticas de el indice despues de
cargar la tabla.

UPDATE STATISTICS dbo.POC_CoverIndex WITH FULLSCAN;
GO

3 - Ejecuta la senetencia select cuantas veces sea necesario, hasta que
estemos convencidos de lo que vemos, que es el scan de la tabla, pues no
tenemos estadisticas para determinar las filas que machan esa expresion.

4 - Prende la opcion, o en su lugar crea la estadistica a mano.


ALTER DATABASE prueba
SET AUTO_CREATE_STATISTICS ON;
GO


CREATE STATISTICS POC_CoverIndex_C
ON dbo.POC_CoverIndex(C) WITH FULLSCAN;
GO

5 - Limpia el cache de procedimientos por si acaso.

DBCC freeproccache;
GO

Fijate que tu mismo comentas sobre la estadistica generada automaticamente
sobre la columna C, en tu codigo de ejemplo. Pero eso no quiere decir que
el
optimizador puso esa estadistica en el indice, sino que creo una nueva
para
poder estimar expresiones sobre esa columna y la crea justo por eso,
porque
no tenia de donde sacar numero alguno para estimar la cardinalidad de la
expresion.

Si miramos las estadisticas almacenadas en esta nueva estadistica que se
creo (valga aqui la redondancia):

DBCC SHOW_STATISTICS ('dbo.POC_CoverIndex', 'POC_CoverIndex_C');
GO

Vemos que la segunda fila en el histograma, dice que hay 9,997 filas en el
rango > 1 y <= 9999, que una fila tiene el valor de la columna C = 9999 y
que
9997 de el resto de los valores son unicos. Por lo que podemos estimar que
solo una fila cumple la expresion C = 500.


Vuelvo a repetir, si el indice que tenemos es (A, B, C), en este caso
nonclustered, y ademas no tenemos indice clustered, y la expresion en el
predicado es:

...
where B = ?

ó

...
where C = ?
entonces SQL Server no

entonces el optimizador no tiene de donde estimar el numero de filas que
pueden machar esa expresion. Es por eso que es importante tener prendida
la
opcion AUTO_CREATE_STATISTICS para que nuevas estadisticas se generen
cuando
estas hagan falta. Tambien es importante tener prendida la opcion
AUTO_UPDATE_STATISTICS para que estas estadisticas se actualizen a medida
que
insertamos nuevas filas o actualizamos o borramos filas existentes.



AMB



"Jose Mariano Alvarez" wrote:

Va el ejemplo de lo que dije.
Lo probe en 2000. 2005 y 2008
Espero sirva




use prueba
go



SET NOCOUNT ON
GO


SET STATISTICS PROFILE OFF
go



CREATE TABLE dbo.POC_CoverIndex(
A smallint NOT NULL,
B smallint NOT NULL,
C int NOT NULL,
descrip char(255) NOT NULL
)
GO
ALTER TABLE dbo.POC_CoverIndex
ADD CONSTRAINT PK_POC_CoverIndex PRIMARY KEY NONCLUSTERED (
A,B,C
)
GO



declare @I int
set @i= 10000

While @i > 0
begin
insert into dbo.POC_CoverIndex
values(@i/10000,@i%1000,@i,convert(char(255),@i))
set @i = @i -1
end










if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) >> '8'
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
else
select * from sys.indexes where object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )



if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) >> '8' --
SQL Server 2000
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
and
name like '_WA_Sys%'
else
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





SET STATISTICS PROFILE ON



Select * from dbo.POC_CoverIndex where c = 500




SET STATISTICS PROFILE OFF




if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) >> '8'
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
else
select * from sys.indexes where object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) >> '8' --
SQL Server 2000
select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
and
name like '_WA_Sys%'
else
SELECT * FROM sys.stats WHERE object_id = OBJECT_ID (
'dbo.POC_CoverIndex' )





declare @StatName varchar(255)
if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) >> '8' --
SQL Server 2000
SELECT @StatName = name
from sysindexes
where id = OBJECT_ID ( 'dbo.POC_CoverIndex' ) and name like '_WA_Sys%'
else
SELECT @StatName = name
FROM sys.stats
WHERE object_id = OBJECT_ID ('dbo.POC_CoverIndex' ) and auto_created = 1
dbcc show_statistics('dbo.POC_CoverIndex', @StatName )








DROP TABLE dbo.POC_CoverIndex
GO






Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase.
Por
favor tratar 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.










"Alejandro Mesa" wrote in
message
news:
> Jose Mariano Alvarez,
>
>> Alejandro, si la condicion sobre esa columna (c3 = ?) es muy
>> convergente,
>> supongamos en extremo 1 registro
>
> Eso lo sabes tu, pero SQL Server no tiene idea de cuantos registros
> cumplen
> esa condicion en ese indice puesto que no hay estadisticas para saberlo
> y
> no
> va a tomar el riesgo de scanear el indice para luego hacer key lookup.
>
> Puedo estar equivocado, puesto que en cada version el codigo de l
> optimizador de queries es mejorado.
>
> Te propongo hagas una prueba a ver si logras lo que dices.
>
>
> AMB
>
>
>
> "Jose Mariano Alvarez" wrote:
>
>> Alejandro, si la condicion sobre esa columna (c3 = ?) es muy
>> convergente,
>> supongamos en extremo 1 registro, y si la cantidad de paginas de la
>> tabla
>> es
>> grande en comparacion al indice, va a hacer un index scan y luego el
>> lookup
>> ya que eso es menos costoso que el scan de la table. Si la cantidad de
>> registros crece, va a llegar un punto que el costo que produce la
>> estructura
>> de los indices y la aleatorizacion de accesos del nonclustered index
>> que
>> va
>> a preferir un acceso mediante un table scan.
>>
>>
>> Saludos
>>
>>
>> Ing. Jose Mariano Alvarez
>> SQLTotal Consulting
>>
>> (Cambia los ceros por O y saca lo que sobra)
>>
>> Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna
>> clase.
>> Por
>> favor tratar 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.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> "Alejandro Mesa" wrote in
>> message
>> news:
>> > Corrección:
>> >
>> >> no asi para:
>> >>
>> >> ...
>> >> where c3 = ?
>> >>
>> >> en cuyo caso puede usarse el valor de "All density" ligado a esa
>> >> columna,
>> >> pero este valor no es tan exacto como el de la distribucion de el
>> >> histograma.
>> >
>> > Me contradije enesta declaracion, pues no existe valor de "All
>> > Density"
>> > solo
>> > para esa columna. La combinacion es progresiva empezando desde la
>> > izquierda y
>> > debe incluir las columnas previas. Por eso no es posible estimar el
>> > numero
>> > de
>> > filas que pueden machar la expresion:
>> >
>> > ...
>> > where c3 = ?
>> >
>> > y por lo tanto se debera hacer un scan de la tabla o el indice
>> > clustered
Respuesta Responder a este mensaje
#10 Alejandro Mesa
10/02/2009 - 01:48 | Informe spam
Jose Mariano Alvarez,

La pregunta se refiere a si SQL Server usara el indice o no, si es que no se
usa la columna lider en la expresion de filtro en el predicado, y mi
respuesta fue que SQL Server no podra estimar este valor si la columna lider
de la clave no es usada. Cuando digo no podra estimar, me refiero a que con
las estadisticas existentes, no podra hacerlo y por tanto tendra que optar
por hacer un scan de la tabla o de el indice clustered, o para ampliar mas la
respuesta, tendra que crear nuevas estadisticas, no solo para "where cP0",
sino para "where B=? and c=?" o "where B = ?".

Si se agregan nuevas estadisticas, es debido a la falta de las mismas. Como
te demostre en el post anterior, si la opcion de creacion automatica de
estadisticas esta apagada, entonces SQL Server no tendra la mas minima idea
de que hay una fila que cumple con esa expresion.

No se porque mencionas la frase "cover index", puesto que un indice es
considerado como "covered o cubierto" si en el se encuentra toda la data
referenciada en la sentencia, incluyendo el predicado mas la lista de
columnas, y el indice que usas de ejemplo no es un "covered index" para la
sentencia que usastes, porque en tu lista de columnas (*) se incluye la
columna [descript] y esa columna no es parte de ese indice.

>> ALTER TABLE dbo.POC_CoverIndex
>> ADD CONSTRAINT PK_POC_CoverIndex PRIMARY KEY NONCLUSTERED (
>> A,B,C
>> )
>> GO



Este indice no se considera "convered index" para la sentencia.

select *
from dbo.POC_CoverIndex
where C = 500;

Mi pregunta es:

Si la opcion de creacion automatica de estadisticas esta apagada, y ademas
esa estadistica no se creo de antemano, automatica o manualmente, como sabe
SQL Server que existe una fila que cumple con la expresion "where C = 500"?

Al menos sabemos que las estadisticas almacenadas sobre el indice (A, B, C)
no son de ayuda en este caso y eso es a lo que me referi en mi post.

No se porque asumes que esta opcion de creacion automatica de estadisticas
va a estar prendida siempre.

Por ultimo, si el predicado es:

...
where A = ? and C = ?;

o

...
where A = ? and B = ?;

o

...
where A = ? and B = ? and C = ?;

El optimizador no necesitara agregar una nueva estadistica para saber si
usar el indice o no.

Que crees que pasaria si al estar apagada la opcion AUTO_CREATE_STATISTICS,
cambiamos la expresion a:

...
where B = 1000 and C = 500;

El optimizador no podra usar las estadisticas de el indice (A, B, C), ni la
estadistica que creamos sobre (C), manual o automatica. SQL Server tendra que
crear otra estadistica nueva para poder estimar cardinalidad y analizar el
costo de usar ese indice.

Sin esas estadisticas, SQL Server no usara ese indice del todo.


AMB


Subject: Re: La regla de la izquierda -- Indices 2/9/2009 2:47 PM PST

By: Jose Mariano Alvarez In: microsoft.public.es.sqlserver


Alejandro, pues creo que la confusion es semantica ya que lo que exprese
coincide con lo que sucede y ademas es totalmente consistente con tu
razonamiento y con el mio. Simplemente nunca dije que la estadistica se
agregaba al indice sino que podia usar el indice como "cover index" haciendo
un INDEX SCAN sobre el mismo.

Simplemente creo que me mal-interpretaste:

La pregunta original fue:
Por tanto en nuestro ejemplo solo sacarian provecho del indice las consultas
SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x AND NAME
= y AND ADRESS = Z

En tu correo donde te autocorregias expresaste
y por lo tanto se debera hacer un scan de la tabla o el indice clustered en
caso de este existir.

Lo cual a mi criterio no es correcto ya que no es lo que sucede



Como que no es lo que sucede, entonces que fue lo que demostre?

AMB


"Jose Mariano Alvarez" wrote:

Alejandro, pues creo que la confusion es semantica ya que lo que exprese
coincide con lo que sucede y ademas es totalmente consistente con tu
razonamiento y con el mio. Simplemente nunca dije que la estadistica se
agregaba al indice sino que podia usar el indice como "cover index" haciendo
un INDEX SCAN sobre el mismo.

Simplemente creo que me mal-interpretaste:

La pregunta original fue:
Por tanto en nuestro ejemplo solo sacarian provecho del indice las consultas
SELECT ... WHERE ID = x, o WHERE ID = X AND NAME = y o WHERE ID = x AND NAME
= y AND ADRESS = Z

En tu correo donde te autocorregias expresaste
y por lo tanto se debera hacer un scan de la tabla o el indice clustered en
caso de este existir.

Lo cual a mi criterio no es correcto ya que no es lo que sucede Esto lo
exprese en mi correo y queria que se hiciera notar ya que no se si MySql lo
puede aprovechar de la misma manera que SQL Server

Lo que exprese fue:
Alejandro, si la condicion sobre esa columna (c3 = ?) es muy convergente,
supongamos en extremo 1 registro, y si la cantidad de paginas de la tabla es
grande en comparacion al indice, va a hacer un index scan y luego el lookup
ya que eso es menos costoso que el scan de la table. Si la cantidad de
registros crece, va a llegar un punto que el costo que produce la estructura
de los indices y la aleatorizacion de accesos del nonclustered index que va
a preferir un acceso mediante un table scan.

Nunca exprese que haria un INDEX SEEK para obtener 1 registro sino que
implicitamente asumi que el SQL Server sabe que hay un solo registro. Aqui
omiti expresar lo de las estadisticas generadas automaticamente asi como que
me estaba refiriendo a un nonclustered index..

Tu me respondiste
Eso lo sabes tu, pero SQL Server no tiene idea de cuantos registros cumplen
esa condicion en ese indice puesto que no hay estadisticas para saberlo y no
va a tomar el riesgo de scanear el indice para luego hacer key lookup

Por eso envie el ejemplo que no coincide con esta frase.
Luego si exprese lo de las estadisticas en mi correo del ejemplo y tu lo
reflejas en tu ultimo correo.

Por lo tanto
IMPORTANTE
***********************************************************************
La respuesta exacta es NO, otras consultas
tambien pueden sacar provecho del indice
aun sin usar la regla de la izquierda.
***********************************************************************

Creo que coincidimos luego de agregar los detalles que faltaban en las
frases.
Espero que les sirva a quienes lo leen ya que creo es bastante rico como
ejemplo..



Saludos


Ing. Jose Mariano Alvarez
SQLTotal Consulting

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

Este mensaje se proporciona tal como es, SIN GARANTIAS de ninguna clase. Por
favor tratar 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.










"Alejandro Mesa" wrote in message
news:
> Jose Mariano Alvarez,
>
> Creo que tienes una confución aqui, o quizas sea yo quien la tenga, asi
> que
> vamos a tratar de averiguar como el optimizador determino que solo una
> fila
> macha esa expresion.
>
> Logicamente queel optimizador no saco esta conclusión de las estadisticas
> normales de ese indice, pues como ya comente anteriormente, tenemos
> estadiscas sobre la distribucion de valores de la columna lider, en este
> caso
> A, y tenemos valores de densidad para la combinacion de columnas de el
> indice, combinacion de izquierda a derecha (A), (A, B), (A, B, C).
>
> DBCC SHOW_STATISTICS ('dbo.POC_CoverIndex', 'PK_POC_CoverIndex');
> GO
>
> Entonces de donde saco el optimizador el valor estimado de el numero de
> filas que cumplen la expresion?
>
> Bueno, si la base de datos tiene prendida la opción
> "AUTO_CREATE_STATISTICS", la cual por lo general debe estar prendida,
> entonces al analizar la consulta, este crea una estadistica para la
> columna
> C, pues no existe un indice que nos pueda proveer estadisticas sobre esta
> columna por si sola. Al ver que solo una fila macha esta expresion,
> entonces
> decide scanear el indice nonclustered, que es mucho mas estrecho que la
> tabla, pues solo contiene informacion sobre A, B, C y luego hace un lookup
> en
> la tabla para traer el valor de la columna [descrip]. Este plan es mucho
> menos costoso que leer toda la tabla para encontrar la fila que macha con
> esa
> expresion, porque este puede estar al final de la tabla.
>
> Como podemos probar lo dicho?
>
> 1 - Apagamos la opcion AUTO_CREATE_STATISTICS en la db donde se hace la
> prueba. Esto antes de ejecutar ela sentencia select.
>
> ALTER DATABASE prueba
> SET AUTO_CREATE_STATISTICS OFF;
> GO
>
> 2 - Para ser justo, actualizamos las estadisticas de el indice despues de
> cargar la tabla.
>
> UPDATE STATISTICS dbo.POC_CoverIndex WITH FULLSCAN;
> GO
>
> 3 - Ejecuta la senetencia select cuantas veces sea necesario, hasta que
> estemos convencidos de lo que vemos, que es el scan de la tabla, pues no
> tenemos estadisticas para determinar las filas que machan esa expresion.
>
> 4 - Prende la opcion, o en su lugar crea la estadistica a mano.
>
>
> ALTER DATABASE prueba
> SET AUTO_CREATE_STATISTICS ON;
> GO
>
>
> CREATE STATISTICS POC_CoverIndex_C
> ON dbo.POC_CoverIndex(C) WITH FULLSCAN;
> GO
>
> 5 - Limpia el cache de procedimientos por si acaso.
>
> DBCC freeproccache;
> GO
>
> Fijate que tu mismo comentas sobre la estadistica generada automaticamente
> sobre la columna C, en tu codigo de ejemplo. Pero eso no quiere decir que
> el
> optimizador puso esa estadistica en el indice, sino que creo una nueva
> para
> poder estimar expresiones sobre esa columna y la crea justo por eso,
> porque
> no tenia de donde sacar numero alguno para estimar la cardinalidad de la
> expresion.
>
> Si miramos las estadisticas almacenadas en esta nueva estadistica que se
> creo (valga aqui la redondancia):
>
> DBCC SHOW_STATISTICS ('dbo.POC_CoverIndex', 'POC_CoverIndex_C');
> GO
>
> Vemos que la segunda fila en el histograma, dice que hay 9,997 filas en el
> rango > 1 y <= 9999, que una fila tiene el valor de la columna C = 9999 y
> que
> 9997 de el resto de los valores son unicos. Por lo que podemos estimar que
> solo una fila cumple la expresion C = 500.
>
>
> Vuelvo a repetir, si el indice que tenemos es (A, B, C), en este caso
> nonclustered, y ademas no tenemos indice clustered, y la expresion en el
> predicado es:
>
> ...
> where B = ?
>
> ó
>
> ...
> where C = ?
> entonces SQL Server no
>
> entonces el optimizador no tiene de donde estimar el numero de filas que
> pueden machar esa expresion. Es por eso que es importante tener prendida
> la
> opcion AUTO_CREATE_STATISTICS para que nuevas estadisticas se generen
> cuando
> estas hagan falta. Tambien es importante tener prendida la opcion
> AUTO_UPDATE_STATISTICS para que estas estadisticas se actualizen a medida
> que
> insertamos nuevas filas o actualizamos o borramos filas existentes.
>
>
>
> AMB
>
>
>
> "Jose Mariano Alvarez" wrote:
>
>> Va el ejemplo de lo que dije.
>> Lo probe en 2000. 2005 y 2008
>> Espero sirva
>>
>>
>>
>>
>> use prueba
>> go
>>
>>
>>
>> SET NOCOUNT ON
>> GO
>>
>>
>> SET STATISTICS PROFILE OFF
>> go
>>
>>
>>
>> CREATE TABLE dbo.POC_CoverIndex(
>> A smallint NOT NULL,
>> B smallint NOT NULL,
>> C int NOT NULL,
>> descrip char(255) NOT NULL
>> )
>> GO
>> ALTER TABLE dbo.POC_CoverIndex
>> ADD CONSTRAINT PK_POC_CoverIndex PRIMARY KEY NONCLUSTERED (
>> A,B,C
>> )
>> GO
>>
>>
>>
>> declare @I int
>> set @i= 10000
>>
>> While @i > 0
>> begin
>> insert into dbo.POC_CoverIndex
>> values(@i/10000,@i%1000,@i,convert(char(255),@i))
>> set @i = @i -1
>> end
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) > >> '8'
>> select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
>> else
>> select * from sys.indexes where object_id = OBJECT_ID (
>> 'dbo.POC_CoverIndex' )
>>
>>
>>
>> if substring(cast(serverproperty('ProductVersion') as varchar(40)),1,1) > >> '8' --
>> SQL Server 2000
>> select * from sysindexes where id = OBJECT_ID ( 'dbo.POC_CoverIndex' )
>> and
>> name like '_WA_Sys%'
>> else
Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida