Anda di halaman 1dari 12

El desempeo de una aplicacin est directamente relacionado al buen o mal diseo de

los ndices de la base de datos.


Para demostrar esto tomemos como ejemplo la tabla de usuarios de un sistema
cualquiera, la cual tiene la siguiente estructura:

Esta tabla no tiene ningn ndice creado, por lo cual SQL Server tratar la tabla como
un HEAP. Un heap es una estructura de datos que almacena la posicin fsica en la que
se almacen cada nueva fila dentro de las pginas asignadas a la tabla.
Puesto que esta tabla no tiene ningn tipo de ndice, es bastante eficiente para agregar
nuevas filas a la tabla pero muy ineficiente para encontrar una fila especfica, esto se
debe a que es necesario leer toda la tabla para obtener el resultado deseado.
Para ilustrar esto, realicemos el siguiente experimento: utilizando el procedimiento
almacenado CrearUsuarios, crearemos 100.000 usuarios de los cuales el 10.000 no est
activo y su fecha de creacin esta en los ltimos 600 das.
exec CrearUsuarios 100000, 10000, 600
Ahora realicemos una consulta para validar el usuario al inicio de sesin del sistema.
SELECT Passwor d, Act i vo FROM Usuar i o
WHERE User name = ' Usuar i o123'
La respuesta probablemente funcione bastante rpido, ya que al recin haber creado los
datos, todas estas filas estn en memoria, pero veamos el plan de ejecucin de esta
consulta presionando el botn de la barra de herramientas del SQL Server
Management Studio y luego ejecutando la misma consulta.

Al pasar el mouse sobre el primer elemento de la izquierda se puede observar el costo
de la consulta.

El costo estimado de la consulta es de 0.685675 y la forma de resolverlo fue un Table
Scan, lo que implica leer toda la tabla.
Para obtener ms informacin sobre el acceso a los datos requeridos para resolver la
consulta ejecutamos la siguiente consulta:
CHECKPOINT

DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS
SET STATISTICS IO ON

SELECT Password, Activo FROM Usuario
WHERE Username ='Usuario123'

SET STATISTICS IO OFF
Lo primero que pasa al ejecutar esta consulta es que SQL Server escribe todos los
cambios pendientes al disco, la segunda instruccin elimina todos los datos que tiene en
memoria. La combinacin de estas dos instrucciones obliga a SQL Server a leer todo
desde disco nuevamente, es importante tener en cuenta que al ejecutar DBCC
DropCleanBuffers se produce un fuerte impacto en el desempeo de todos los usuarios,
por lo que no se debe utilizar en servidores de produccin.
La tercera instruccin nos permite obtener informacin sobre las lecturas de datos
requeridas para contestar una consulta. El resultado que se obtiene en el rea de
mensajes es:

( 1 r ow( s) af f ect ed)
Tabl e ' Usuar i o' . Scan count 1, l ogi cal r eads 774, physi cal r eads 3, r ead- ahead r eads
773, l ob l ogi cal r eads 0, l ob physi cal r eads 0, l ob r ead- ahead r eads 0.
Esto nos dice que se accedi a la tabla Usuario, se hizo una lectura completa de la
tabla 1 vez, lo que equivale a 774 pginas ledas, como cada pgina pesa 8Kb, 774 *
8kb es igual a 6 Mb, precisamente lo mismo que pesa la tabla completa.
Las lecturas fsicas son las pginas que no se encontraban en memoria cuando SQL
Server las necesitaba, en este caso fueron 3, algo extrao ya que vaciamos el cache
antes de ejecutar la consulta por lo cual no debera existir ninguna pgina en memoria,
pero SQL Server es ms inteligente y cada vez que tiene que leer pginas desde el disco,
lo cual es una operacin muy costosa, lee tambin otras pginas cercanas que puedan
ser tiles para responder la consulta que solicit la lectura. En este caso SQL Server fue
capaz de Leer 773 de las 774 pginas utilizando este mecanismo de lecturas anticipadas
(read-ahead).
Las lob o Large Object Block, son operaciones relacionadas a datos que no se
guardan junto con la fila como los campos de tipo TEXT, IMAGE y los tipos de datos
que sobrepasen los 8000 bytes de la pgina. En este caso no hay operaciones de este
tipo.
Para mejorar el desempeo de las consultas se utilizan ndices, los ms utilizados son
los Clustered y Non-Clustered.
Existen otros 3 tipos de ndices que se utilizan para mejorar los tiempos de acceso a
datos XML, a bsquedas de texto y de datos espaciales. A continuacin se muestra la
disponibilidad segn la versin de SQL Server:
Clustered
Index
Non-
Clustered
Index
Full Text
Index
Xml Index Spatial
Index
SQL Server
2000
si si - - -
SQL Server
2005
si si (1) si si -
SQL Server
2008
si si (1 y 2) si si si
(1) Permite definir Columnas Incluidas (2) Permite definir ndices Filtrados
Los Clustered Indexes son ndices que controlan el orden fsico de las filas en la tabla,
por lo cual solo puede existir uno para cada tabla.
Los Non-Clustered indexes son ndices que mantienen un sub conjunto de las columnas
de la tabla en orden. Estos indices no modifican el orden de las filas de la tabla, en
lugar de esto mantienen una lista ordenada de referencias a filas de la tabla original.
Para ilustrar la diferencia entre estos 2 tipos de ndices podemos decir que las pginas
blancas de la gua telefnica tienen un clustered index por Apellido(s) y Nombres, con
lo cual puedo buscar de forma muy eficiente el nmero de telfono de una persona si
conozco sus apellidos y su nombre, una vez que lo encuentro obtendr su nmero de
telfono en forma inmediata pues el numero est al lado del nombre.
En el caso de las pginas amarillas de la gua telefnica la forma de buscar es un poco
distinta, en este caso busco por rubro. Primero busco en un ndice, el cual me indica en
qu pgina se encuentra la lista de empresas que satisfacen la condicin que busco. Esto
mismo es lo que pasa cuando utilizo un ndice Non-Clustered index una vez que
encuentro lo que quiero en el ndice debo ir a leer la fila especfica para obtener el resto
de los datos.
Veamos qu pasa cuando agregamos un ndice a la columna Username de la tabla
usuario creada anteriormente.

El ndice ser Non-Clustered y nico puesto que no podemos tener ms de un usuario
con el mismo nombre.
Al volver a ejecutar la misma consulta, obtenemos lo siguiente:

El plan de ejecucin es un poco ms complicado pero esta consulta es 100 veces menos
costosa que la anterior. Ahora la consulta utiliza el ndice para encontrar el RID, que es
el identificador de la fila, con este RID hace una bsqueda en la tabla de tipo heap (RID
Lookup).
Esta reduccin de costo se explica por la cantidad de accesos a datos que esta consulta
requiere, puesto que estos bajan desde 774 a solo 4 pginas lo que equivale 32 kb de
datos contra 6192 kb, que eran necesarios antes de la creacin del ndice.

( 1 r ow( s) af f ect ed)
Tabl e ' Usuar i o' . Scan count 0, l ogi cal r eads 4, physi cal r eads 1, r ead- ahead r eads 0,
l ob l ogi cal r eads 0, l ob physi cal r eads 0, l ob r ead- ahead r eads 0.
Veamos otra alternativa, si utilizamos un clustered index en lugar de un non-cluster
index no ser necesario el lookup, por lo que el acceso ser ms eficiente.

Ahora el plan de ejecucin se ve as:
El
acceso se ve as:
Tabl e ' Usuar i o' . Scan count 0, l ogi cal r eads 3, physi cal r eads 2, r ead- ahead r eads 0,
l ob l ogi cal r eads 0, l ob physi cal r eads 0, l ob r ead- ahead r eads 0.
Como se puede ver el costo de esta consulta ahora es la mitad que con el ndice non-
clustered y en lugar de 4 lecturas lgicas tenemos slo 2.
Es importante destacar que siempre recomendable utilizar tablas que utilicen un Cluster
index en lugar de tablas que solo utilicen ndices non-cluster.
El clustered index controla el orden fsico de las filas en la tabla, a diferencia de los
ndices Non-Clustered que funcionan como una lista ordenada de identificadores de fila.
La siguiente ilustracin muestra la estructura que tiene un clustered index.

Todas las tablas que tienen un clustered index tienen un nodo raz y muchos nodos en
los niveles intermedios, estos a su vez pueden apuntar a nodos hojas o a otros nodos
intermedios. Esta estructura forma un rbol (B-Tree) que permite encontrar cualquier
fila en forma eficiente.
La bsqueda parte desde el nodo raz, este nodo tiene una lista de llaves, se comparan
estas llaves para encontrar el nodo de nivel intermedio que contenga un rango de llaves
que cubra la llave que se est buscando. Luego se repite el proceso en los nodos
intermedios hasta que se encuentre la pgina de datos que contenga la fila especfica.
Para ilustrar este proceso, realicemos una bsqueda sobre un clustered index de la llave
123.
Contenido del Nodo Raz (ID 0)
Llave ID Nodo
Intermedio
1 1
100 2
160 3
300 4
500 5
1000 6
Contenido del Nodo Intermedio (ID 2)
Llave ID Nodo
Intermedio
100 10
110 11
120 12
130 13
140 14
150 15
Contenido del Nodo Hoja (ID 12)
Llave Columna 1 Columna 2 Columna N
120 AX06 10000 XXX
121 AX02 10004 XXX
122 AX07 10000 XXX
123 AX04 20000 XXX
124 AX08 9000 XXX
125 AX01 1 XXX
Para obtener el resultado se lee el nodo raz, se busca el nodo intermedio que contiene a
la llave 123, en este caso el nodo 2 contiene filas con llave entre 100 y 160. Luego se
repite el proceso, el nodo 12 contiene filas con llaves entre 120 y 130. El nodo 12 es un
pgina de datos por lo cual no necesitamos seguir buscando.
Cada vez que se agrega una fila a la tabla, SQL Server debe insertar la nueva fila en la
posicin correcta dentro del ndice, esto puede ser una operacin simple y eficiente si es
que la pgina es la ltima del ndice o si la pgina tiene espacio disponible. Si la pgina
no tiene espacio es necesario dividir la pgina en 2, algo conocido como Page Split, que
deja 2 pginas con un 50% de utilizacin.
Cada vez que se elimina una fila de la tabla, SQL Server eliminar la fila de la pgina,
sin modificar ninguna otra pgina, lo cual limita el impacto de la operacin a 1 sola
pgina pero causa que se desperdicie mayor porcentaje de las pginas, proceso conocido
como fragmentacin.
Algo aun ms costoso ocurre cuando se actualiza el valor de la llave del ndice
clustered, en este caso SQL Server debe copiar la fila desde la pagina original, aplicar
los cambios indicados en el update, insertar la fila en la nueva pgina y finalmente
eliminar la fila desde la pgina original.
anteriormente vimos como los clustered index controlan el orden fsico de las filas en la
tabla. Ahora veremos cmo operan los ndices Non-Clustered.
La siguiente ilustracin muestra la estructura que tiene un non-clustered index.

Al igual que en el caso de los clustered index, los non-clustered index tienen un nodo
raz y muchos nodos en los niveles intermedios, estos a su vez pueden apuntar a nodos
hojas o a otros nodos intermedios. La diferencia se presenta en los nodos hoja, estos
tienen almacenados solo el Id del registro y no todo el registro, por lo que se hacer
necesario hacer una bsqueda sobre el ndice cluster o sobre el heap para obtener el
resto de las columnas de la fila.
La bsqueda parte desde el nodo raz, este nodo tiene una lista de llaves, se comparan
estas llaves para encontrar el nodo de nivel intermedio que contenga un rango de llaves
que cubra la llave que se est buscando. Luego se repite el proceso en los nodos
intermedios hasta que se encuentre la llave que identifica a la fila correspondiente a la
llave del ndice.
Para ilustrar este proceso, realicemos una bsqueda de la llave AX04 sobre un non-
clustered index.


Paso 1.- Contenido del Nodo Raz (ID 0)
Llave
ndice
ID Nodo
Intermedio
AA01 1
AG01 2
BA01 3
DB02 4
RF04 5
KJ 01 6
Paso 2.- Contenido del Nodo Intermedio (ID 2)
Llave
ndice
ID Nodo
Intermedio
AG01 10
AJ 10 11
AP20 12
AZ30 13
BA20 14
BH50 15
Paso 3.- Contenido del Nodo Hoja (ID 12)
Llave
ndice
Llave
AP20 101
AQ10 50
AR12 160
AX04 123
AX24 145
AY25 12
Paso 4.- Hemos encontrado la fila (123), ahora debemos realizar una bsqueda
utilizando ndice cluster, conocido como bookmark lookup en SQL Server 2000/2005 y
como key lookup en SQL Server 2008.
Llave ID Nodo
Intermedio
1 1
100 2
160 3
300 4
500 5
1000 6
Paso 5.- Contenido del Nodo Intermedio (ID 2)
Llave ID Nodo
Intermedio
100 10
110 11
120 12
130 13
140 14
150 15
Paso 6.- Contenido del Nodo Hoja (ID 12)
Llave Columna 1 Columna 2 Columna N
120 AX06 10000 XXX
121 AX02 10004 XXX
122 AX07 10000 XXX
123 AX04 20000 XXX
124 AX08 9000 XXX
125 AX01 1 XXX
En SQL Server la Llave ndice puede ser una o varias columnas, siempre y cuando el
largo combinado de estas columnas no supere los 900 bytes.
Columnas Incluidas
SQL Server 2005 agreg una nueva funcionalidad a los ndices non-clustered llamada
Columnas Incluidas estas columnas no son parte de la llave ndice, por lo que no se
mantienen ordenadas dentro del ndice y como consecuencia de esto solo es necesario
almacenar su valor en el nodo hoja del ndice.
En el ejemplo anterior, el paso 3 quedara as al agregar la Columna 2 como una
columna incluida del ndice:



Llave
ndice
Llave Columna
Incluida
(Columna 2)
AP20 101 12000
AQ10 50 12332
AR12 160 12344
AX04 123 20000
124 145 12233
125 12 12221
Las columnas incluidas tienen varias ventajas:
Al utilizar columnas incluidas en el ndice es posible superar la limitacin de los
900 bytes para la llave del ndice, manteniendo un ndice eficiente.
Las modificaciones al valor de una columna incluida es ms eficiente que la
modificacin de una columna que es parte de la llave del ndice pues estas no
requieren ser mantenidas en orden.
Es posible crear Covering Indexes, que son ndices que incluyen todas las
columnas requeridas para contestar una consulta especfica, que no requieren la
bsqueda sobre el clustered index. Este tipo de ndice es igual o ms eficiente
que u ndice cluster.
ndices Filtrados
SQL Server 2008 agreg otra mejora a los ndices non-clustered llamada ndices
Filtrados. Estos ndices mantienen ordenados un sub conjunto de las filas de la tabla.
El uso ms comn de este tipo de ndices se da cuando queremos crear un ndice sobre
una columna que permite valores nulos. Al crear un ndice normal podemos
desperdiciar una gran parte del espacio de ndice ordenando filas que tienen un valor
nulo.
A continuacin se describen algunos ejemplos de casos de uso para estos ndices
filtrados:
La columna fecha de trmino de contrato de la tabla empleado contiene una
gran cantidad de filas con el valor nulo.
Los estados intermedios son buenos candidatos para ser ndices filtrados. Es
posible crear un ndice que solo contenga las rdenes de compra recibidas y en
proceso, pero no las despachadas.

Anda mungkin juga menyukai