Cluster Index...

04/11/2005 - 09:59 por Oscar | Informe spam
Hola, aqui seguimos preocupados por el rendimiento del sistema.

Os pongo en situación. En mi empresa habiamos desarrollado un sistema en C#
y Oracle, pero cuando todo estaba listo para producción se decidio cambiar a
SQL-SERVER por temas de coste. Asi que nos pusimos manos a la obra y se
cambio todo el código , se migraron los datos ,la estructura y los
procedimientos de Oracle a SQL_SERVER.

Para realizar esta migración me documente un poco, y consegui de internet
unos cuantos documentos sobre como hacer esta migración. Al pasar las
Primary key a SQL-SERVER se convirtieron en Cluster index. El problema que
tengo ahora es el siguiente:
Tengo unas 5 o 6 tablas con unos 12-13 millones de registros, estas tablas
(bueno en realidad todas las tablas ), tiene como clave primaria un GUID
representado como un Varchar(36). Ademas en estas tablas se realizan
continuamente inserciones y querys, y como os podeis imaginar ordenar los
datos por este guid no tiene ningun beneficio. Sin embargo creo que se
penalizan mucho las inserciones por aquello de la reorganización del árbol
B.

En esta situación me estoy planteando muy seriamente eliminar todos los
Cluster index y crear las claves primarias como indices únicos normales y
corrientes,
y SOLO crear Cluster index en las tablas y en los campos en los que tener
una ordenación física de la tabla me reporte algun benecifio.
¿Es una locura eliminar todos los cluster index?, ¿Me penalizaran los joins,
(aun cuando existan pk )?.


Muchas gracias por vuestras respuestas.


www.metasincro.es

Preguntas similare

Leer las respuestas

#1 Carlos Sacristán
04/11/2005 - 10:21 | Informe spam
Sí, sí que es una pequeña locura que una tabla no tenga un índice
agrupado. Otra cosa es que el campo que escojas como parte integrante de
este índice sea el adecuado, algo que se nota más cuanto más grandes sean
las tablas.

Yo buscaría cuál es el(los) campo(s) que mejor se puede(n) adaptar a ser
ese índice agrupado para que efectivamente la reorganización sea la mínima,
pero siempre le dejaría uno porque el resto de los índices de la tabla se
van a basar en el agrupado...


Un saludo

-
"Sólo sé que no sé nada. " (Sócrates)

"Oscar" escribió en el mensaje
news:ewc#
Hola, aqui seguimos preocupados por el rendimiento del sistema.

Os pongo en situación. En mi empresa habiamos desarrollado un sistema en


C#
y Oracle, pero cuando todo estaba listo para producción se decidio cambiar


a
SQL-SERVER por temas de coste. Asi que nos pusimos manos a la obra y se
cambio todo el código , se migraron los datos ,la estructura y los
procedimientos de Oracle a SQL_SERVER.

Para realizar esta migración me documente un poco, y consegui de internet
unos cuantos documentos sobre como hacer esta migración. Al pasar las
Primary key a SQL-SERVER se convirtieron en Cluster index. El problema que
tengo ahora es el siguiente:
Tengo unas 5 o 6 tablas con unos 12-13 millones de registros, estas tablas
(bueno en realidad todas las tablas ), tiene como clave primaria un GUID
representado como un Varchar(36). Ademas en estas tablas se realizan
continuamente inserciones y querys, y como os podeis imaginar ordenar los
datos por este guid no tiene ningun beneficio. Sin embargo creo que se
penalizan mucho las inserciones por aquello de la reorganización del árbol
B.

En esta situación me estoy planteando muy seriamente eliminar todos los
Cluster index y crear las claves primarias como indices únicos normales y
corrientes,
y SOLO crear Cluster index en las tablas y en los campos en los que tener
una ordenación física de la tabla me reporte algun benecifio.
¿Es una locura eliminar todos los cluster index?, ¿Me penalizaran los


joins,
(aun cuando existan pk )?.


Muchas gracias por vuestras respuestas.


www.metasincro.es


Respuesta Responder a este mensaje
#2 Oscar
04/11/2005 - 10:54 | Informe spam
Hola Carlos,

Algo sobre eso habia leido (los indices no agrupados se basan en el
agrupado), pero que pasa si no hay un indice agrupado???
Supongo que en ese caso el resto de indices haran referencia directamente a
la fila de datos en vez de hacer referencia a un indice, lo cual no me
parece mal ni que ello suponga ninguna merma del rendimiento.

En mi caso particular, y resumiendo un poco, tengo una tabla de informes
con unos 12 millones de registos. como clave primaria un GUID, y aparte de
otros datos un identificador de expediente(id_exp), y un campo fecha. En el
funcionamiento normal de la aplicación se realizan las siguientes tareas:

1) Se obtienen los últmimos 100 informes del expedientes (Select top 100...
from informes where id_exp='X' order by fecha desc)
2) Se inserta un nuevo informe (insert into informes (id_exp,fecha) values
('X1',getdate()))
3) Se realizar un update sobre el últmimo informe insertado update informes
set estado=1;
4) posteriormente se podrian inserta más informes. (pasos 2 y 3)

Estos cuatro pasos forma una tarea básica del sistema que se realiza
constantemente y de forma concurrente.

En esta situación no veo creo que una un cluster indiex me salga rentable,
ya que cada insert podria suponer una reorganización del arbol, lo que cada
vez será más costoso por el volumen de datos y la fragmentacion.. etc.

¿En SQL-SERVER siempre se suelen crear indices agrupados en todas las
tablas? ¿Por que?

Saludos.

www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:
Sí, sí que es una pequeña locura que una tabla no tenga un índice
agrupado. Otra cosa es que el campo que escojas como parte integrante de
este índice sea el adecuado, algo que se nota más cuanto más grandes sean
las tablas.

Yo buscaría cuál es el(los) campo(s) que mejor se puede(n) adaptar a
ser
ese índice agrupado para que efectivamente la reorganización sea la
mínima,
pero siempre le dejaría uno porque el resto de los índices de la tabla se
van a basar en el agrupado...


Un saludo

-
"Sólo sé que no sé nada. " (Sócrates)

"Oscar" escribió en el mensaje
news:ewc#
Hola, aqui seguimos preocupados por el rendimiento del sistema.

Os pongo en situación. En mi empresa habiamos desarrollado un sistema en


C#
y Oracle, pero cuando todo estaba listo para producción se decidio
cambiar


a
SQL-SERVER por temas de coste. Asi que nos pusimos manos a la obra y se
cambio todo el código , se migraron los datos ,la estructura y los
procedimientos de Oracle a SQL_SERVER.

Para realizar esta migración me documente un poco, y consegui de internet
unos cuantos documentos sobre como hacer esta migración. Al pasar las
Primary key a SQL-SERVER se convirtieron en Cluster index. El problema
que
tengo ahora es el siguiente:
Tengo unas 5 o 6 tablas con unos 12-13 millones de registros, estas
tablas
(bueno en realidad todas las tablas ), tiene como clave primaria un GUID
representado como un Varchar(36). Ademas en estas tablas se realizan
continuamente inserciones y querys, y como os podeis imaginar ordenar los
datos por este guid no tiene ningun beneficio. Sin embargo creo que se
penalizan mucho las inserciones por aquello de la reorganización del
árbol
B.

En esta situación me estoy planteando muy seriamente eliminar todos los
Cluster index y crear las claves primarias como indices únicos normales y
corrientes,
y SOLO crear Cluster index en las tablas y en los campos en los que tener
una ordenación física de la tabla me reporte algun benecifio.
¿Es una locura eliminar todos los cluster index?, ¿Me penalizaran los


joins,
(aun cuando existan pk )?.


Muchas gracias por vuestras respuestas.


www.metasincro.es






Respuesta Responder a este mensaje
#3 Oscar
04/11/2005 - 12:52 | Informe spam
Hola de nuevo ,

El tener los datos ordenados físicamente me asusta un poco, ya que como te
comentaba antes ese es el proceso "resumido", para complicar un poco más el
asunto hay que tener en cuenta que la arquitectura real es que existe n
centros formados por una bbdd SQL-server, un servidor y clientes que se
conectan al servidor. Todas las noches se sincronizan las bbdd SQL-SERVER,
de forma que la ordenación de la tabla de informes tendria que hacerla por
id_exp y fecha, y en este caso los informes que vienen de otro centro no se
insertarian al final (ya que es la actividad de todo un dia).
Incluso teniendo en cuenta la actividad de un solo centro el tener los
informe ordenados solo por fecha , al recuperar los 100 últimos informes de
un expediente, estos no se encontraran ordenados de forma consecutiva. Ten
en cuenta que un expediente normalmente generará un informe cada 2 o tres
dias y en un solo dia hay miles de informes de distintos expedientes. Por lo
tanto al obtener los últimos 100 informes SQL-SERVER tendria que recorrer
muchisimas más páginas de datos de las que en principio serian necesarias ,
ya que los últmios 100 informes pueden corresponder a periodos de tiempo muy
dispares desde meses a años, y en un solo dia seguro que se rellenan varias
páginas.

Tal vez el parte del problema sea que provengo del mundo de Oracle donde
todas las tablas en principio son heap tables (sin organzación física),
salvo que explicitamente se creen tablas IOT (Index Organized Table) y estas
tienen bastantes "peros" a la hora de utilizarlas.

Lo que si tengo bastante claro es que tal y como estan los indices ahora
(pk=cluster index) no es ni de lejos la mejor solución.
Durante la semana que viene haré pruebas con estas dos soluciones:

1) Poner cluster index sobre los campos ID_EXP y Fecha

2) Eliminar por completo los cluster index

¿Alguna recomendación ?,

Saludos y muchas gracias por tu tiempo.





www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:uR$G$
Hay varias razones para que una tabla siempre tenga un índice agrupado:
a.. la tabla estará ordenada físicamente por el(los) campo(s) que lo
compongan, mientras que si no existe la tabla está estructurada como un
montón (heap), sin ningún orden (echa un vistazo al tema "Estructuras de
montón" en los BOL)
b.. en cuanto necesites consultar la(s) columna(s) usadas por el índice
agrupado, SQL Server va a leer una extensión (que como sabes son ocho
páginas de datos, es decir, 64Kb) de una vez, lo cual repercute en una mejor
eficacia del sistema para leer los datos del disco. Imagínate esta situación
si necesitas que el motor te devuelva muchos registros. Ahora ponte en la
situación contraria: si no existe índice agrupado, los datos estarán
totalmente fragmentados y SQL Server va a tener que estar leyendo del disco
páginas de datos aleatoriamente situadas, perjudicando notablemente el
rendimiento
c.. con un índice agrupado puedes realizar la operación de defragmentación
(es decir, recomponer los índices para que sus datos estén ordenados y no
existan saltos). Si no existe, no tienes posibilidad de hacerlo porque la
tabla es en sí un conjunto de datos cada vez más y más defragmentados
En cuanto a tu caso en concreto:
1.. un índice agrupado se recomienda para aquellas columnas (entre otras
cosas) sobre las que se van a soler operaciones de ordenamiento (ya que SQL
Server se evita tener que realizarlo al recoger los datos ya ordenados
físicamente). El paso 1 podría recomendar usar el campo fecha como
integrante de ese índice agrupado
2.. al insertar un nuevo informe, si el índice agrupado es id_exp (que
supongo que será la columna GUID), al ser aleatorio, va a obligar al motor a
reorganizar las páginas para introducir ese nuevo valor ya que con toda
probabilidad no será el último (ordenación). Sin embargo, el campo fecha le
asignas el valor de la función GETDATE(), que siempre será el último
(evitamos inserción aleatoria)
3.. los índices no agrupados son recomendables, entre otras cosas, para
búsquedas por coincidencia exacta (operador igual). Si has recogido el valor
GUID introducido en el punto 2, el campo id_exp es un buen candidato a ser
índice NO agrupado
Según los tres puntos anteriores, puedes probar a crear como índice
agrupado al campo fecha y como índice no agrupado id_exp. Tú mismo dices en
el penúltimo párrafo el inconveniente de tener un índice agrupado mal
seleccionado, pero sin embargo si se piensa de otro modo es muy eficiente.

Espero haberte ayudado. De todos modos, te recomiendo la lectura del
libro "A fondo SQL Server 2000", de Kalen Delaney (así como sus artículos al
respecto en SQL Magazine), pues son muy instructivos.


Un saludo

-
"Sólo sé que no sé nada. " (Sócrates)

"Oscar" escribió en el mensaje
news:
Hola Carlos,

Algo sobre eso habia leido (los indices no agrupados se basan en el
agrupado), pero que pasa si no hay un indice agrupado???
Supongo que en ese caso el resto de indices haran referencia directamente
a
la fila de datos en vez de hacer referencia a un indice, lo cual no me
parece mal ni que ello suponga ninguna merma del rendimiento.

En mi caso particular, y resumiendo un poco, tengo una tabla de informes
con unos 12 millones de registos. como clave primaria un GUID, y aparte de
otros datos un identificador de expediente(id_exp), y un campo fecha. En
el
funcionamiento normal de la aplicación se realizan las siguientes tareas:

1) Se obtienen los últmimos 100 informes del expedientes (Select top
100...
from informes where id_exp='X' order by fecha desc)
2) Se inserta un nuevo informe (insert into informes (id_exp,fecha) values
('X1',getdate()))
3) Se realizar un update sobre el últmimo informe insertado update
informes
set estado=1;
4) posteriormente se podrian inserta más informes. (pasos 2 y 3)

Estos cuatro pasos forma una tarea básica del sistema que se realiza
constantemente y de forma concurrente.

En esta situación no veo creo que una un cluster indiex me salga rentable,
ya que cada insert podria suponer una reorganización del arbol, lo que
cada
vez será más costoso por el volumen de datos y la fragmentacion.. etc.

¿En SQL-SERVER siempre se suelen crear indices agrupados en todas las
tablas? ¿Por que?

Saludos.

www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:
> Sí, sí que es una pequeña locura que una tabla no tenga un índice
> agrupado. Otra cosa es que el campo que escojas como parte integrante de
> este índice sea el adecuado, algo que se nota más cuanto más grandes
> sean
> las tablas.
>
> Yo buscaría cuál es el(los) campo(s) que mejor se puede(n) adaptar a
> ser
> ese índice agrupado para que efectivamente la reorganización sea la
> mínima,
> pero siempre le dejaría uno porque el resto de los índices de la tabla
> se
> van a basar en el agrupado...
>
>
> Un saludo
>
> -
> "Sólo sé que no sé nada. " (Sócrates)
>
> "Oscar" escribió en el mensaje
> news:ewc#
>> Hola, aqui seguimos preocupados por el rendimiento del sistema.
>>
>> Os pongo en situación. En mi empresa habiamos desarrollado un sistema
>> en
> C#
>> y Oracle, pero cuando todo estaba listo para producción se decidio
>> cambiar
> a
>> SQL-SERVER por temas de coste. Asi que nos pusimos manos a la obra y se
>> cambio todo el código , se migraron los datos ,la estructura y los
>> procedimientos de Oracle a SQL_SERVER.
>>
>> Para realizar esta migración me documente un poco, y consegui de
>> internet
>> unos cuantos documentos sobre como hacer esta migración. Al pasar las
>> Primary key a SQL-SERVER se convirtieron en Cluster index. El problema
>> que
>> tengo ahora es el siguiente:
>> Tengo unas 5 o 6 tablas con unos 12-13 millones de registros, estas
>> tablas
>> (bueno en realidad todas las tablas ), tiene como clave primaria un
>> GUID
>> representado como un Varchar(36). Ademas en estas tablas se realizan
>> continuamente inserciones y querys, y como os podeis imaginar ordenar
>> los
>> datos por este guid no tiene ningun beneficio. Sin embargo creo que se
>> penalizan mucho las inserciones por aquello de la reorganización del
>> árbol
>> B.
>>
>> En esta situación me estoy planteando muy seriamente eliminar todos los
>> Cluster index y crear las claves primarias como indices únicos normales
>> y
>> corrientes,
>> y SOLO crear Cluster index en las tablas y en los campos en los que
>> tener
>> una ordenación física de la tabla me reporte algun benecifio.
>> ¿Es una locura eliminar todos los cluster index?, ¿Me penalizaran los
> joins,
>> (aun cuando existan pk )?.
>>
>>
>> Muchas gracias por vuestras respuestas.
>>
>>
>> www.metasincro.es
>>
>>
>
>


Respuesta Responder a este mensaje
#4 Miguel Egea
04/11/2005 - 19:17 | Informe spam
Hola Oscar, verás realmente el orden físico te ayudará tal y como te ha
dicho carlos, si no existe ese orden físico lo que tendrás serán punteros a
la clave primaria, pero siempre puedes crear indices que recubrarn tus
consultas y otro montón de técnicas que mejoren tu rendimiento.

Cada tabla tiene un índice clusterd que es el más a decuado, generalmente es
el creciente, pero si no hay uno que sea creciente siempre se puede ajustar
el fillfactor para minimizar el hecho de que páginas se tengan que dividir
muy a menudo por este tipo de conflictos (esto es conocido como page-split).

Sobre la sincronización no le veo demasiado problema, incluso podrías crear
tablas para cada centro y unirlas (sobre todo si acabas pasando a SQL 2005
en el que el concepto de particionado de tablas tiene más soporte que con
las vistas que hay que hacerlo en SQL 2000), pero en tu caso seguramente
incluso lo de las vistas tenga sencillo.

Una recomendación es que cambies el tipo varchar(36) de tus guid al tipo de
datos guid, eso segurammente optimize algo tus consultas. (creo recordar que
un guid ocupa exactamente la mitad de eso es decir 4 bytes).

Si tus joins son típicamente por guid, baja el fillfactor por ejemplo a 70%
(supone potencialmente un 30% de fragmentación, y deberías ajustarlo para
minimizar el page-split maximizando las lecturas).

Si tus joins son tipicamente por id_Exp y fecha, que sea el id_exp el
clustered index. si se insertan registros del mismo centro ordenados aunque
sean en grupos es posible que tu page-split no se incremente tanto como
potencialmente parece. Además si eso se hace fuera de horas de trabajo, que
no te preocupe mucho.

Si una tabla no es consultada junto con otras normalmente comprueba cual es
el order by más característico quizá ese sea un buen índice clustered.

Para ver el impacto en lecturas puede usar lo siguiente

Crea el índice clustered por el campo que quieras
set statistics io on
ejecuta tus querys más habituales
anota resultados

haz lo mismo con otro candidato a índice clustered. (Create un ranking de
mejor a peor)

Para ver el impacto de las escrituras consulta el page-split simulando
muchas inserciones, pon profiler y exporta luego a una tabla para sumar
lecturas y escrituras. Cambia el índice clustered y comprueba diferencias.

Luego piensa en como se producen tus escrituras y cuantas son con respecto a
las lecturas y en función de ello toma la decisión de como crear tu índice
clusterd.


Espero que te sirva


Miguel Egea
Visita mi web http://www.portalsql.com
SQL Server MVP, Mentor
Solid Quality Learning
http://www.SolidQualityLearning.com
"Solid Quality Learning is the trusted global provider of advanced education
and solutions for the entire Microsoft database platform"




"Oscar" wrote in message
news:
Hola de nuevo ,

El tener los datos ordenados físicamente me asusta un poco, ya que como te
comentaba antes ese es el proceso "resumido", para complicar un poco más
el asunto hay que tener en cuenta que la arquitectura real es que existe
n centros formados por una bbdd SQL-server, un servidor y clientes que se
conectan al servidor. Todas las noches se sincronizan las bbdd SQL-SERVER,
de forma que la ordenación de la tabla de informes tendria que hacerla por
id_exp y fecha, y en este caso los informes que vienen de otro centro no
se insertarian al final (ya que es la actividad de todo un dia).
Incluso teniendo en cuenta la actividad de un solo centro el tener los
informe ordenados solo por fecha , al recuperar los 100 últimos informes
de un expediente, estos no se encontraran ordenados de forma consecutiva.
Ten en cuenta que un expediente normalmente generará un informe cada 2 o
tres dias y en un solo dia hay miles de informes de distintos expedientes.
Por lo tanto al obtener los últimos 100 informes SQL-SERVER tendria que
recorrer muchisimas más páginas de datos de las que en principio serian
necesarias , ya que los últmios 100 informes pueden corresponder a
periodos de tiempo muy dispares desde meses a años, y en un solo dia
seguro que se rellenan varias páginas.

Tal vez el parte del problema sea que provengo del mundo de Oracle donde
todas las tablas en principio son heap tables (sin organzación física),
salvo que explicitamente se creen tablas IOT (Index Organized Table) y
estas tienen bastantes "peros" a la hora de utilizarlas.

Lo que si tengo bastante claro es que tal y como estan los indices ahora
(pk=cluster index) no es ni de lejos la mejor solución.
Durante la semana que viene haré pruebas con estas dos soluciones:

1) Poner cluster index sobre los campos ID_EXP y Fecha

2) Eliminar por completo los cluster index

¿Alguna recomendación ?,

Saludos y muchas gracias por tu tiempo.





www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:uR$G$
Hay varias razones para que una tabla siempre tenga un índice agrupado:
a.. la tabla estará ordenada físicamente por el(los) campo(s) que lo
compongan, mientras que si no existe la tabla está estructurada como un
montón (heap), sin ningún orden (echa un vistazo al tema "Estructuras de
montón" en los BOL)
b.. en cuanto necesites consultar la(s) columna(s) usadas por el índice
agrupado, SQL Server va a leer una extensión (que como sabes son ocho
páginas de datos, es decir, 64Kb) de una vez, lo cual repercute en una
mejor eficacia del sistema para leer los datos del disco. Imagínate esta
situación si necesitas que el motor te devuelva muchos registros. Ahora
ponte en la situación contraria: si no existe índice agrupado, los datos
estarán totalmente fragmentados y SQL Server va a tener que estar leyendo
del disco páginas de datos aleatoriamente situadas, perjudicando
notablemente el rendimiento
c.. con un índice agrupado puedes realizar la operación de
defragmentación (es decir, recomponer los índices para que sus datos estén
ordenados y no existan saltos). Si no existe, no tienes posibilidad de
hacerlo porque la tabla es en sí un conjunto de datos cada vez más y más
defragmentados
En cuanto a tu caso en concreto:
1.. un índice agrupado se recomienda para aquellas columnas (entre otras
cosas) sobre las que se van a soler operaciones de ordenamiento (ya que
SQL Server se evita tener que realizarlo al recoger los datos ya ordenados
físicamente). El paso 1 podría recomendar usar el campo fecha como
integrante de ese índice agrupado
2.. al insertar un nuevo informe, si el índice agrupado es id_exp (que
supongo que será la columna GUID), al ser aleatorio, va a obligar al motor
a reorganizar las páginas para introducir ese nuevo valor ya que con toda
probabilidad no será el último (ordenación). Sin embargo, el campo fecha
le asignas el valor de la función GETDATE(), que siempre será el último
(evitamos inserción aleatoria)
3.. los índices no agrupados son recomendables, entre otras cosas, para
búsquedas por coincidencia exacta (operador igual). Si has recogido el
valor GUID introducido en el punto 2, el campo id_exp es un buen candidato
a ser índice NO agrupado
Según los tres puntos anteriores, puedes probar a crear como índice
agrupado al campo fecha y como índice no agrupado id_exp. Tú mismo dices
en el penúltimo párrafo el inconveniente de tener un índice agrupado mal
seleccionado, pero sin embargo si se piensa de otro modo es muy eficiente.

Espero haberte ayudado. De todos modos, te recomiendo la lectura del
libro "A fondo SQL Server 2000", de Kalen Delaney (así como sus artículos
al respecto en SQL Magazine), pues son muy instructivos.


Un saludo

-
"Sólo sé que no sé nada. " (Sócrates)

"Oscar" escribió en el mensaje
news:
Hola Carlos,

Algo sobre eso habia leido (los indices no agrupados se basan en el
agrupado), pero que pasa si no hay un indice agrupado???
Supongo que en ese caso el resto de indices haran referencia directamente
a
la fila de datos en vez de hacer referencia a un indice, lo cual no me
parece mal ni que ello suponga ninguna merma del rendimiento.

En mi caso particular, y resumiendo un poco, tengo una tabla de informes
con unos 12 millones de registos. como clave primaria un GUID, y aparte
de
otros datos un identificador de expediente(id_exp), y un campo fecha. En
el
funcionamiento normal de la aplicación se realizan las siguientes tareas:

1) Se obtienen los últmimos 100 informes del expedientes (Select top
100...
from informes where id_exp='X' order by fecha desc)
2) Se inserta un nuevo informe (insert into informes (id_exp,fecha)
values
('X1',getdate()))
3) Se realizar un update sobre el últmimo informe insertado update
informes
set estado=1;
4) posteriormente se podrian inserta más informes. (pasos 2 y 3)

Estos cuatro pasos forma una tarea básica del sistema que se realiza
constantemente y de forma concurrente.

En esta situación no veo creo que una un cluster indiex me salga
rentable,
ya que cada insert podria suponer una reorganización del arbol, lo que
cada
vez será más costoso por el volumen de datos y la fragmentacion.. etc.

¿En SQL-SERVER siempre se suelen crear indices agrupados en todas las
tablas? ¿Por que?

Saludos.

www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:
> Sí, sí que es una pequeña locura que una tabla no tenga un índice
> agrupado. Otra cosa es que el campo que escojas como parte integrante
> de
> este índice sea el adecuado, algo que se nota más cuanto más grandes
> sean
> las tablas.
>
> Yo buscaría cuál es el(los) campo(s) que mejor se puede(n) adaptar a
> ser
> ese índice agrupado para que efectivamente la reorganización sea la
> mínima,
> pero siempre le dejaría uno porque el resto de los índices de la tabla
> se
> van a basar en el agrupado...
>
>
> Un saludo
>
> -
> "Sólo sé que no sé nada. " (Sócrates)
>
> "Oscar" escribió en el mensaje
> news:ewc#
>> Hola, aqui seguimos preocupados por el rendimiento del sistema.
>>
>> Os pongo en situación. En mi empresa habiamos desarrollado un sistema
>> en
> C#
>> y Oracle, pero cuando todo estaba listo para producción se decidio
>> cambiar
> a
>> SQL-SERVER por temas de coste. Asi que nos pusimos manos a la obra y
>> se
>> cambio todo el código , se migraron los datos ,la estructura y los
>> procedimientos de Oracle a SQL_SERVER.
>>
>> Para realizar esta migración me documente un poco, y consegui de
>> internet
>> unos cuantos documentos sobre como hacer esta migración. Al pasar las
>> Primary key a SQL-SERVER se convirtieron en Cluster index. El problema
>> que
>> tengo ahora es el siguiente:
>> Tengo unas 5 o 6 tablas con unos 12-13 millones de registros, estas
>> tablas
>> (bueno en realidad todas las tablas ), tiene como clave primaria un
>> GUID
>> representado como un Varchar(36). Ademas en estas tablas se realizan
>> continuamente inserciones y querys, y como os podeis imaginar ordenar
>> los
>> datos por este guid no tiene ningun beneficio. Sin embargo creo que se
>> penalizan mucho las inserciones por aquello de la reorganización del
>> árbol
>> B.
>>
>> En esta situación me estoy planteando muy seriamente eliminar todos
>> los
>> Cluster index y crear las claves primarias como indices únicos
>> normales y
>> corrientes,
>> y SOLO crear Cluster index en las tablas y en los campos en los que
>> tener
>> una ordenación física de la tabla me reporte algun benecifio.
>> ¿Es una locura eliminar todos los cluster index?, ¿Me penalizaran los
> joins,
>> (aun cuando existan pk )?.
>>
>>
>> Muchas gracias por vuestras respuestas.
>>
>>
>> www.metasincro.es
>>
>>
>
>






Respuesta Responder a este mensaje
#5 Miguel Egea
04/11/2005 - 19:22 | Informe spam
perdonad, 36/2 y no 16 :-S, tendré que volver a estudiar aritmética :-)


Miguel Egea
Visita mi web http://www.portalsql.com
SQL Server MVP, Mentor
Solid Quality Learning
http://www.SolidQualityLearning.com
"Solid Quality Learning is the trusted global provider of advanced education
and solutions for the entire Microsoft database platform"

"Miguel Egea" wrote in message
news:%

Hola Oscar, verás realmente el orden físico te ayudará tal y como te ha
dicho carlos, si no existe ese orden físico lo que tendrás serán punteros
a la clave primaria, pero siempre puedes crear indices que recubrarn tus
consultas y otro montón de técnicas que mejoren tu rendimiento.

Cada tabla tiene un índice clusterd que es el más a decuado, generalmente
es el creciente, pero si no hay uno que sea creciente siempre se puede
ajustar el fillfactor para minimizar el hecho de que páginas se tengan que
dividir muy a menudo por este tipo de conflictos (esto es conocido como
page-split).

Sobre la sincronización no le veo demasiado problema, incluso podrías
crear tablas para cada centro y unirlas (sobre todo si acabas pasando a
SQL 2005 en el que el concepto de particionado de tablas tiene más
soporte que con las vistas que hay que hacerlo en SQL 2000), pero en tu
caso seguramente incluso lo de las vistas tenga sencillo.

Una recomendación es que cambies el tipo varchar(36) de tus guid al tipo
de datos guid, eso segurammente optimize algo tus consultas. (creo
recordar que un guid ocupa exactamente la mitad de eso es decir 4 bytes).

Si tus joins son típicamente por guid, baja el fillfactor por ejemplo a
70% (supone potencialmente un 30% de fragmentación, y deberías ajustarlo
para minimizar el page-split maximizando las lecturas).

Si tus joins son tipicamente por id_Exp y fecha, que sea el id_exp el
clustered index. si se insertan registros del mismo centro ordenados
aunque sean en grupos es posible que tu page-split no se incremente tanto
como potencialmente parece. Además si eso se hace fuera de horas de
trabajo, que no te preocupe mucho.

Si una tabla no es consultada junto con otras normalmente comprueba cual
es el order by más característico quizá ese sea un buen índice clustered.

Para ver el impacto en lecturas puede usar lo siguiente

Crea el índice clustered por el campo que quieras
set statistics io on
ejecuta tus querys más habituales
anota resultados

haz lo mismo con otro candidato a índice clustered. (Create un ranking de
mejor a peor)

Para ver el impacto de las escrituras consulta el page-split simulando
muchas inserciones, pon profiler y exporta luego a una tabla para sumar
lecturas y escrituras. Cambia el índice clustered y comprueba diferencias.

Luego piensa en como se producen tus escrituras y cuantas son con respecto
a las lecturas y en función de ello toma la decisión de como crear tu
índice clusterd.


Espero que te sirva


Miguel Egea
Visita mi web http://www.portalsql.com
SQL Server MVP, Mentor
Solid Quality Learning
http://www.SolidQualityLearning.com
"Solid Quality Learning is the trusted global provider of advanced
education and solutions for the entire Microsoft database platform"




"Oscar" wrote in message
news:
Hola de nuevo ,

El tener los datos ordenados físicamente me asusta un poco, ya que como
te comentaba antes ese es el proceso "resumido", para complicar un poco
más el asunto hay que tener en cuenta que la arquitectura real es que
existe n centros formados por una bbdd SQL-server, un servidor y clientes
que se conectan al servidor. Todas las noches se sincronizan las bbdd
SQL-SERVER, de forma que la ordenación de la tabla de informes tendria
que hacerla por id_exp y fecha, y en este caso los informes que vienen
de otro centro no se insertarian al final (ya que es la actividad de todo
un dia).
Incluso teniendo en cuenta la actividad de un solo centro el tener los
informe ordenados solo por fecha , al recuperar los 100 últimos informes
de un expediente, estos no se encontraran ordenados de forma consecutiva.
Ten en cuenta que un expediente normalmente generará un informe cada 2 o
tres dias y en un solo dia hay miles de informes de distintos
expedientes. Por lo tanto al obtener los últimos 100 informes SQL-SERVER
tendria que recorrer muchisimas más páginas de datos de las que en
principio serian necesarias , ya que los últmios 100 informes pueden
corresponder a periodos de tiempo muy dispares desde meses a años, y en
un solo dia seguro que se rellenan varias páginas.

Tal vez el parte del problema sea que provengo del mundo de Oracle donde
todas las tablas en principio son heap tables (sin organzación física),
salvo que explicitamente se creen tablas IOT (Index Organized Table) y
estas tienen bastantes "peros" a la hora de utilizarlas.

Lo que si tengo bastante claro es que tal y como estan los indices ahora
(pk=cluster index) no es ni de lejos la mejor solución.
Durante la semana que viene haré pruebas con estas dos soluciones:

1) Poner cluster index sobre los campos ID_EXP y Fecha

2) Eliminar por completo los cluster index

¿Alguna recomendación ?,

Saludos y muchas gracias por tu tiempo.





www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:uR$G$
Hay varias razones para que una tabla siempre tenga un índice
agrupado:
a.. la tabla estará ordenada físicamente por el(los) campo(s) que lo
compongan, mientras que si no existe la tabla está estructurada como un
montón (heap), sin ningún orden (echa un vistazo al tema "Estructuras de
montón" en los BOL)
b.. en cuanto necesites consultar la(s) columna(s) usadas por el índice
agrupado, SQL Server va a leer una extensión (que como sabes son ocho
páginas de datos, es decir, 64Kb) de una vez, lo cual repercute en una
mejor eficacia del sistema para leer los datos del disco. Imagínate esta
situación si necesitas que el motor te devuelva muchos registros. Ahora
ponte en la situación contraria: si no existe índice agrupado, los datos
estarán totalmente fragmentados y SQL Server va a tener que estar leyendo
del disco páginas de datos aleatoriamente situadas, perjudicando
notablemente el rendimiento
c.. con un índice agrupado puedes realizar la operación de
defragmentación (es decir, recomponer los índices para que sus datos
estén ordenados y no existan saltos). Si no existe, no tienes posibilidad
de hacerlo porque la tabla es en sí un conjunto de datos cada vez más y
más defragmentados
En cuanto a tu caso en concreto:
1.. un índice agrupado se recomienda para aquellas columnas (entre otras
cosas) sobre las que se van a soler operaciones de ordenamiento (ya que
SQL Server se evita tener que realizarlo al recoger los datos ya
ordenados físicamente). El paso 1 podría recomendar usar el campo fecha
como integrante de ese índice agrupado
2.. al insertar un nuevo informe, si el índice agrupado es id_exp (que
supongo que será la columna GUID), al ser aleatorio, va a obligar al
motor a reorganizar las páginas para introducir ese nuevo valor ya que
con toda probabilidad no será el último (ordenación). Sin embargo, el
campo fecha le asignas el valor de la función GETDATE(), que siempre será
el último (evitamos inserción aleatoria)
3.. los índices no agrupados son recomendables, entre otras cosas, para
búsquedas por coincidencia exacta (operador igual). Si has recogido el
valor GUID introducido en el punto 2, el campo id_exp es un buen
candidato a ser índice NO agrupado
Según los tres puntos anteriores, puedes probar a crear como índice
agrupado al campo fecha y como índice no agrupado id_exp. Tú mismo dices
en el penúltimo párrafo el inconveniente de tener un índice agrupado mal
seleccionado, pero sin embargo si se piensa de otro modo es muy
eficiente.

Espero haberte ayudado. De todos modos, te recomiendo la lectura del
libro "A fondo SQL Server 2000", de Kalen Delaney (así como sus artículos
al respecto en SQL Magazine), pues son muy instructivos.


Un saludo

-
"Sólo sé que no sé nada. " (Sócrates)

"Oscar" escribió en el mensaje
news:
Hola Carlos,

Algo sobre eso habia leido (los indices no agrupados se basan en el
agrupado), pero que pasa si no hay un indice agrupado???
Supongo que en ese caso el resto de indices haran referencia
directamente a
la fila de datos en vez de hacer referencia a un indice, lo cual no me
parece mal ni que ello suponga ninguna merma del rendimiento.

En mi caso particular, y resumiendo un poco, tengo una tabla de
informes
con unos 12 millones de registos. como clave primaria un GUID, y aparte
de
otros datos un identificador de expediente(id_exp), y un campo fecha. En
el
funcionamiento normal de la aplicación se realizan las siguientes
tareas:

1) Se obtienen los últmimos 100 informes del expedientes (Select top
100...
from informes where id_exp='X' order by fecha desc)
2) Se inserta un nuevo informe (insert into informes (id_exp,fecha)
values
('X1',getdate()))
3) Se realizar un update sobre el últmimo informe insertado update
informes
set estado=1;
4) posteriormente se podrian inserta más informes. (pasos 2 y 3)

Estos cuatro pasos forma una tarea básica del sistema que se realiza
constantemente y de forma concurrente.

En esta situación no veo creo que una un cluster indiex me salga
rentable,
ya que cada insert podria suponer una reorganización del arbol, lo que
cada
vez será más costoso por el volumen de datos y la fragmentacion.. etc.

¿En SQL-SERVER siempre se suelen crear indices agrupados en todas las
tablas? ¿Por que?

Saludos.

www.metasincro.es
"Carlos Sacristán" <csacristanARROBAmvpsPUNTOorg> wrote in message
news:
> Sí, sí que es una pequeña locura que una tabla no tenga un índice
> agrupado. Otra cosa es que el campo que escojas como parte integrante
> de
> este índice sea el adecuado, algo que se nota más cuanto más grandes
> sean
> las tablas.
>
> Yo buscaría cuál es el(los) campo(s) que mejor se puede(n) adaptar
> a
> ser
> ese índice agrupado para que efectivamente la reorganización sea la
> mínima,
> pero siempre le dejaría uno porque el resto de los índices de la tabla
> se
> van a basar en el agrupado...
>
>
> Un saludo
>
> -
> "Sólo sé que no sé nada. " (Sócrates)
>
> "Oscar" escribió en el mensaje
> news:ewc#
>> Hola, aqui seguimos preocupados por el rendimiento del sistema.
>>
>> Os pongo en situación. En mi empresa habiamos desarrollado un sistema
>> en
> C#
>> y Oracle, pero cuando todo estaba listo para producción se decidio
>> cambiar
> a
>> SQL-SERVER por temas de coste. Asi que nos pusimos manos a la obra y
>> se
>> cambio todo el código , se migraron los datos ,la estructura y los
>> procedimientos de Oracle a SQL_SERVER.
>>
>> Para realizar esta migración me documente un poco, y consegui de
>> internet
>> unos cuantos documentos sobre como hacer esta migración. Al pasar las
>> Primary key a SQL-SERVER se convirtieron en Cluster index. El
>> problema
>> que
>> tengo ahora es el siguiente:
>> Tengo unas 5 o 6 tablas con unos 12-13 millones de registros, estas
>> tablas
>> (bueno en realidad todas las tablas ), tiene como clave primaria un
>> GUID
>> representado como un Varchar(36). Ademas en estas tablas se realizan
>> continuamente inserciones y querys, y como os podeis imaginar ordenar
>> los
>> datos por este guid no tiene ningun beneficio. Sin embargo creo que
>> se
>> penalizan mucho las inserciones por aquello de la reorganización del
>> árbol
>> B.
>>
>> En esta situación me estoy planteando muy seriamente eliminar todos
>> los
>> Cluster index y crear las claves primarias como indices únicos
>> normales y
>> corrientes,
>> y SOLO crear Cluster index en las tablas y en los campos en los que
>> tener
>> una ordenación física de la tabla me reporte algun benecifio.
>> ¿Es una locura eliminar todos los cluster index?, ¿Me penalizaran los
> joins,
>> (aun cuando existan pk )?.
>>
>>
>> Muchas gracias por vuestras respuestas.
>>
>>
>> www.metasincro.es
>>
>>
>
>










email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida