Вы находитесь на странице: 1из 31

Distintas formas de optimizar las consultas realizadas en SQL.

Por Claudio El lenguaje SQL es no procedimental, es decir, en las sentencias se indica que queremos conseguir y no como lo tiene que hacer el interprete para conseguirlo. Esto es pura teora, pues en la prctica a todos los gestores de SQL hay que especificar sus propios truquitos para optimizar el rendimiento.

Por tanto, muchas veces no basta con especificar una sentencia SQL correcta, sino que adems, hay que indicarle como tiene que hacerlo si queremos que el tiempo de respuesta sea el mnimo. En este apartado veremos como mejorar el tiempo de respuesta de nuestro interprete ante unas determinadas situaciones: Diseo de las tablas

Normaliza las tablas, al menos hasta la tercera forma normal, para asegurar que no hay duplicidad de datos y se aprovecha al mximo el almacenamiento en las tablas. Si hay que desnormalizar alguna tabla piensa en la ocupacin y en el rendimiento antes de proceder. Los primeros campos de cada tabla deben ser aquellos campos requeridos y dentro de los requeridos primero se definen los de longitud fija y despus los de longitud variable. Ajusta al mximo el tamao de los campos para no desperdiciar espacio. Es muy habitual dejar un campo de texto para observaciones en las tablas. Si este campo se va a utilizar con poca frecuencia o si se ha definido con gran tamao, por si acaso, es mejor crear una nueva tabla que contenga la clave primaria de la primera y el campo para observaciones.

Gestin y eleccin de los ndices Los ndices son campos elegidos arbitrariamente por el constructor de la base de datos que permiten la bsqueda a partir de dicho campo a una velocidad notablemente superior. Sin embargo, esta ventaja se ve

contrarrestada por el hecho de ocupar mucha ms memoria (el doble ms o menos) y de requerir para su insercin y actualizacin un tiempo de proceso superior. Evidentemente, no podemos indexar todos los campos de una tabla extensa ya que doblamos el tamao de la base de datos. Igualmente, tampoco sirve de mucho el indexar todos los campos en una tabla pequea ya que las selecciones pueden efectuarse rpidamente de todos modos. Un caso en el que los ndices pueden resultar muy tiles es cuando realizamos peticiones simultneas sobre varias tablas. En este caso, el proceso de seleccin puede acelerarse sensiblemente si indexamos los campos que sirven de nexo entre las dos tablas. Los ndices pueden resultar contraproducentes si los introducimos sobre campos triviales a partir de los cuales no se realiza ningn tipo de peticin ya que, adems del problema de memoria ya mencionado, estamos ralentizando otras tareas de la base de datos como son la edicin, insercin y borrado. Es por ello que vale la pena pensrselo dos veces antes de indexar un campo que no sirve de criterio para bsquedas o que es usado con muy poca frecuencia por razones de mantenimiento. Campos a Seleccionar

En la medida de lo posible hay que evitar que las sentencias SQL estn embebidas dentro del cdigo de la aplicacin. Es mucho ms eficaz usar vistas o procedimientos almacenados por que el gestor los guarda compilados. Si se trata de una sentencia embebida el gestor debe compilarla antes de ejecutarla. Seleccionar exclusivamente aquellos que se necesiten No utilizar nunca SELECT * por que el gestor debe leer primero la estructura de la tabla antes de ejecutar la sentencia Si utilizas varias tablas en la consulta especifica siempre a que tabla pertenece cada campo, le ahorras al gestor el tiempo de localizar a que tabla pertenece el campo. En lugar de SELECT Nombre, Factura FROM Clientes, Facturacion WHERE IdCliente = IdClienteFacturado, usa:

SELECT Clientes.Nombre, Facturacion.Factura WHERE Clientes.IdCliente = Facturacion.IdClienteFacturado. Campos de Filtro

Se procurar elegir en la clusula WHERE aquellos campos que formen parte de la clave del fichero por el cual interrogamos. Adems se especificarn en el mismo orden en el que estn definidos en la clave. Interrogar siempre por campos que sean clave. Si deseamos interrogar por campos pertenecientes a ndices compuestos es mejor utilizar todos los campos de todos los ndices. Supongamos que tenemos un ndice formado por el campo NOMBRE y el campo APELLIDO y otro ndice formado por el campo EDAD. La sentencia WHERE NOMBRE='Juan' AND APELLIDO Like '%' AND EDAD = 20 sera ms optima que WHERE NOMBRE = 'Juan' AND EDAD = 20 por que el gestor, en este segundo caso, no puede usar el primer ndice y ambas sentencias son equivalentes por que la condicin APELLIDO Like '%' devolvera todos los registros.

Orden de las Tablas Cuando se utilizan varias tablas dentro de la consulta hay que tener cuidado con el orden empleado en la clusula FROM. Si deseamos saber cuantos alumnos se matricularon en el ao 1996 y escribimos: FROM Alumnos, Matriculas WHERE Alumno.IdAlumno = Matriculas.IdAlumno AND Matriculas.Ao = 1996 el gestor recorrer todos los alumnos para buscar sus matriculas y devolver las correspondientes. Si escribimos FROM Matriculas, Alumnos WHERE Matriculas.Ao = 1996 AND Matriculas.IdAlumno = Alumnos.IdAlumnos, el gestor filtra las matrculas y despus selecciona los alumnos, de esta forma tiene que recorrer menos registros.

Comentar algunos errores comunes observados en numerosas instalaciones: 1) En uniones de consultas es mejor el uso de UNION ALL en vez de UNION si ambas subconsultas no pueden devolver datos repetidos. 2) Las LEFT JOIN y RIGHT JOIN son en realidad OUTER JOINs a pesar de que no se explicite la palabra OUTER.

3) En el uso de ndices no es necesario utilizar todos los campos del mismo pero no es ptimo utilizar un campo si no se han informado los campos previos por igualdad . esto solo funciona en ADO 2.8 para arriba o en SQL server 2000. Para usar el LIKE en ADO 2.7 para abajo deben cambiarse los comodines '%' por los comodines '*' (asteriscos). De no hacerlo el LIKE funcionara buscando un STRING que contenga el % Ejemplos: BUSCA TODO LO Q TENGA H EN Mi_Campo en ADO <= 2.7 SELECT * FROM Mi_Tabla WHERE Mi_Campo LIKE '*H*' BUSCA TODO LO Q TENGA H EN Mi_Campo en ADO >= 2.8 y SQL SERVER SELECT * FROM Mi_Tabla WHERE Mi_Campo LIKE '%H%' 1.Es preferible realizar las relaciones entra tablas usando INNER JOIN, LEFT JOIN, RIGHT JOIN ... y no realizar la relacin con la clusula WHERE. 2. No se recomienda usar clusula muy frecuentes como LIKE 3. Utilizar lo menos posible ANY, SOME, EXISTS, IN (SELECT Campo1 From Tabla2) 4. Utilizar FILEGROUPS, lo q permite asignar una base de datos, tabla, indices o determinados campos TEXT o IMAGES hacia diferentes archivos, lo cual permite una excelente aceleracin. 5. Colocar las bases de datos en diferentes discos duros 6. Configurar los campos con la misma intercalacin. 5. No utilizar cursores!!!!! 6. No utilizar tablas temporales con # o ## 7. Utilizar para poco volumen de datos en lugar de cursores las llamadas variables tipo tablas: DECLARE T1 TABLE (CAMPO1 VARCHAR(1)) 8. Utilizar vistas en lugar de consultas gigantes en tus StoreProc. o mezclar el uso de estas, porque recordemos que las vistas son ya pre-compiladas. Query Optimizer. Index Selection. Seleccin de ndice adecuado. SQL Server. Tema: VII

En este tema voy a comentar como podemos verificar que se est usando el ndice de una forma correcta en una consulta, ya que no solo por que aparezca el ndice en el plan de ejecucin de la consulta ha de ser correcto. Por dar una primera pincelada, si nosotros encontramos en un plan de ejecucin, donde un ndice se esta usando como Index Scan, muy probablemente no se este usando de la forma adecuada, ya que Index Scan para obtener su resultado ha de pasar por todas los campos del ndice. Mientras que si encontramos un Index Seek, forma normal de utilizacin de un ndice, solo se accede para obtener el resultado a los campos selectivos por la consulta del ndice. Es aconsejable para el buen entendimiento de este Tema:VII que se lea o repase los enlaces: Query Optimizer. Parameter Sniffing. SQL Server. Tema: I y el enlace: Query Optimizer. Cardinality Estimation Error. SQL Server. Tema: II, y sus temas posteriors.

Normalmente, partiendo de escenarios con ndices y estadsticas actualizadas, cuando usamos consultas donde filtramos por un valor especfico como por ejemplo: Select ProductID, SalesOrderID, salesOrderDetailID form sales. salesOrderDetail where ProductID =771 Os voy a mostrar un ejemplo en un plan de ejecucin donde se ve la forma correcta de cmo ha de usarse un ndice,. Veremos que usa el operador: Index Seek, y verificamos que usa predicados de bsqueda: Seek Predicates:

Se suelen dar en casos donde utilizamos funciones o diferentes expresiones para filtrar en las consultas, como por ejemplo: Select ProductID, SalesOrderID, salesOrderDetailID form sales. salesOrderDetail where ABS(ProductID) =771 quizs SQL Server, no va a utiliza los ndices deforma correcta. En el ejemplo que os muestro en el plan de ejecucin de la consulta, vemos que usa Index Scan, donde hace un scan del indice que por lo menos es mejor hacer un scan de la tabla (Table Scan). Vemos que no tenemos un Seek Predicates pero si un Predicate -> esto no es bueno, ya que hace un sacan de todo el ndice para buscar los valores especficos de ProductID.

Obviamente, podemos estar en escenarios con ndices de ms de una columna, y con varios predicados, como es el caso en del ejemplo: Select ProductID, SalesOrderID, salesOrderDetailID form sales. salesOrderDetail where ProductID =771 AND SalesOrderID=45233 para este caso, el resultado es muy bueno por que usa un Index Seek y nos hemos de fijar que en el Seek Predicates hace la bsqueda por las dos columnas ProducID y SalesOrderID:

Como ultimo caso, voy a mostrar una mezcla de los casos anteriores: Select ProductID, SalesOrderID, salesOrderDetailID form sales. salesOrderDetail where ProductID =771 AND ABS(SalesOrderID)=45233 en estos casos puede ser mas difcil de encontrar un problema aunque veamos que usa un Index Seek y nos parezca que todo esta perfecto, realmente no lo esta, por que en el Seek Predicates solo busca por ProductID, y no por la funcin ABS(salesOrderID), donde vemos que hace su busqueda en el Predicate: (El ndice hace dos operaciones, primero busca el ProductID, haciendo uso del Index Seek, y segundo busca por SalesOrderID haciendo un Scan de la columna en ndice)

Actualizacin de estadsticas sncronas o asncronas mejoran la respuesta del optimizador de consultas. SQL Server Las estadsticas usadas para la optimizacin de consulta, son objetos que contienen informacin estadstica acerca de la distribucin de valores en una o ms columnas de una tabla o vista indexada. El optimizador de consultas utiliza las estadsticas para estimar la cardinalidad o el nmero de filas del resultado de la consulta, lo que hace posible que el optimizador de consultas pueda crear un plan de consulta de alta calidad.

Hay 3 opciones de estadsticas, configurables, a nivel de cada base de datos: AUTO_CREATE_STATISTICS AUTO_UPDATE_STATISTICS AUTO_UPDATE_STATISTICS_ASYNC AUTO_CREATE_STATISTICS y AUTO_UPDATE_STATISTICS La opcin automtica de creacin de estadsticas, AUTO_CREATE_STATISTICS, y la de actualizacin de estadsticas, AUTO_UPDATE_STATISTICS, estn activadas de forma predeterminada: ALTER DATABASE TU_BaseDatos SET AUTO_CREATE_STATISTICS ON; ALTER DATABASE TU_BaseDatos SET AUTO_UPDATE_STATISTICS ON; GO Estas actualizaciones de las estadsticas son sincronas, las consultas siempre se compilan y ejecutan con estadsticas actualizadas; cuando las estadsticas estn obsoletas, el optimizador de consultas espera a que las estadsticas estn actualizadas antes de compilar y ejecutar la consulta. Se aconseja su uso cuando se realiza operaciones que cambian la distribucin de los datos, como truncar una tabla o realizar una actualizacin masiva de un gran porcentaje de las filas. Si no actualiza las estadsticas despus de completar la operacin, el uso de estadsticas sincrnicas garantizar que las estadsticas estn actualizadas antes de ejecutar las consultas en los datos cambiados. AUTO_UPDATE_STATISTICS_ASYNC La opcin automtica de creacin de estadsticas asincronas, AUTO_UPDATE_STATISTICS_ASYNC, no estn activadas de forma predeterminada: ALTER DATABASE TU_BaseDatos SET AUTO_UPDATE_STATISTICS_ASYNC ON; GO

Estas actualizaciones de las estadsticas son asincrnicas, las consultas se compilan con las estadsticas existentes incluso aunque estn anticuadas; el optimizador de consultas podra elegir un plan de consulta poco ptimo si las estadsticas estn obsoletas cuando se compila la consulta. Las consultas que se compilan cuando las actualizaciones asincrnicas se han completado se beneficiarn del uso de estadsticas actualizadas. Se aconseja su uso: Cuando su aplicacin ejecuta frecuentemente la misma consulta, consultas similares o los planes de consulta almacenados en memoria cach similares. Sus tiempos de respuesta a la consulta podran ser ms predecibles con actualizaciones asincrnicas de las estadsticas que con actualizaciones sincrnicas, porque el optimizador de consultas puede ejecutar las consultas de entrada sin esperar a que las estadsticas se actualicen Si su aplicacin ha experimentado tiempos de espera de solicitud de cliente causados por una o varias consultas que aguardaban la actualizacin de estadsticas. En algunos casos, la espera por las estadsticas sincrnicas podra causar errores en aplicaciones con tiempos de espera agresivos.

Usar estadsticas sincronas y asincronas, de forma conjunta. La opcin AUTO_UPDATE_STATISTICS_ASYNC se establece en el nivel de la base de datos y determina el mtodo de actualizacin para todas las estadsticas de la base de datos. Slo es aplicable a la actualizacin de estadsticas y no se puede usar para crear estadsticas de forma asincrnica. El establecimiento de esta opcin en ON no tiene ningn efecto a menos que AUTO_UPDATE_STATISTICS tambin se establezca en ON. De forma predeterminada, la opcin AUTO_UPDATE_STATISTICS_ASYNC est en OFF. En aquellos escenarios donde no tenemos un control total sobre las operaciones que se realizan en la base de datos y no podemos hilar siempre muy fino es preferible tener actualizaciones sncronas, de esta forma no

obtendremos la mejor de las latencias y posiblemente suframos en algunas consultas, pero minimizamos el riesgo de tener pocas consultas optimizadas, en base a unas estadsticas no adecuadas, que nos pueden dar un gran disgusto. Estadsticas filtradas CREATE STATISTICS Las estadsticas filtradas pueden mejorar el rendimiento de las consultas. Para la mayora de las consultas, el optimizador de consultas genera ya las estadsticas necesarias para un plan de consulta de alta calidad; en algunos casos, para mejorar el rendimiento de la consulta necesita crear estadsticas adicionales con CREATE STATISTICS. A modo de ejemplo, se crean las estadsticas NameStatistic para todas las filas de las columnas Colum1ID y Colum2 de la tabla TBA y se deshabilita la posibilidad de volver a calcular las estadsticas automticamente CREATE STATISTICS NameStatistic ON Tu_BaseDatos. TBA.TBA (Colum1ID, Colum2) WITH FULLSCAN, NORECOMPUTE; Utilizar esta opcin puede producir planes de consulta poco ptimos. Se recomienda usar esta opcin con moderacin y que lo haga nicamente un administrador de sistemas cualificado. Activar actualizacin automtica de estadsticas en SQL 2000 Para activar la actualizacin automtica de estadsticas en SQL 2000:

--habilita: auto create statistics sp_dboption TubaseDatos, 'auto create statistics', 'ON' GO --habilita: auto update statistics sp_dboption TubaseDatos, 'auto update statistics', 'ON' GO --habilita: sp_autostats EXEC sp_autostats 'ON' GO

Cuando se actualizan las estadsticas automticas

Para tablas con muchas filas, hemos de tener cuidado ya que las estadsticas se actualizan automticamente cuando se han cambiado (insert/update/delete) mas del 20% de la cantidad de filas actuales de la tabla. Ese valor se guarda en la columna [rowmodctr] en la tabla de sistema [sysindexes]. Por poner un ejemplo, en una tabla con 80.000.000 registros, e imaginando que hay un promedio de 200.000 registros modificados por da. Y luego solo se hacen select el resto del da: 100.00 * (200,000 / 80,000,000) = 0.25 Como veis, la cantidad de filas que se insertan en un da equivalen al 0.25, de la cantidad de filas actuales y por tanto SQL Server no actualizara las estadsticas hasta que el valor en [rowmodctr] sea el 20% de las filas. Por eso hay que vigilar de cerca las tablas con muchas filas y de ser posible buscar el tiempo adecuado para actualizar sus estadsticas. Ya que puede penalizar la creacin de los planes de ejecucin, en estas tablas.

Para forzar la actualizacin de estadsticas, en todos los objetos de las bases de datos, para evitar estar en el anterior escenario comentado:

--Actualizo estadisticas EXEC sp_updatestats GO

Os paso el procedimiento que nos dice el tamao de un tabla de nuestra base de datos:

sp_spaceused 'Nombre_De_Tu_Tabla'

Os paso un procedimiento para ver los tamaos de todas las tablas de una base de datos, en SQL Server 2000: (En versiones posteriores, esta informacin se muestra desde el Management Studio)

CREATE PROCEDURE dbo.TableSpaceUsed AS -- Create the temporary table... CREATE TABLE #tblResults ( [name] nvarchar(20), [rows] int, [reserved] varchar(18), [reserved_int] int default(0), [data] varchar(18), [data_int] int default(0), [index_size] varchar(18), [index_size_int] int default(0), [unused] varchar(18), [unused_int] int default(0) ) -- Populate the temp table... EXEC sp_MSforeachtable @command1= "INSERT INTO #tblResults ([name],[rows],[reserved],[data],[index_size],[unused]) EXEC sp_spaceused '?'" -- Strip out the " KB" portion from the fields UPDATE #tblResults SET [reserved_int] = CAST(SUBSTRING([reserved], 1, CHARINDEX(' ', [reserved])) AS int), [data_int] = CAST(SUBSTRING([data], 1, CHARINDEX(' ', [data])) AS int), [index_size_int] = CAST(SUBSTRING([index_size], 1, CHARINDEX(' ', [index_size])) AS int), [unused_int] = CAST(SUBSTRING([unused], 1, CHARINDEX(' ', [unused])) AS int)

-- Return the results... SELECT * FROM #tblResults

Como calcular la longitud de los campos de todas las tablas de una bbdd --Longitud de campo de todas las tablas en sql sever 2005 SET NOCOUNT ON DBCC UPDATEUSAGE(0) -- DB size. EXEC sp_spaceused-- Table row counts and sizes. CREATE TABLE #t ( [name] NVARCHAR(128), [rows] CHAR(11), reserved VARCHAR(18), data VARCHAR(18), index_size VARCHAR(18), unused VARCHAR(18)) INSERT #t EXEC sp_msForEachTable 'EXEC sp_spaceused ''?''' SELECT *FROM #t-- # of rows. SELECT SUM(CAST([rows] AS int)) AS [rows]FROM #t DROP TABLE #t --en lugar de select sum(cast(rows as int) que dice el nmero total de filas, puedes poner SELECT SUM(CAST([rows] AS int)) AS [rows], sum(cast(reserved as flaot))*1024 as bytereservados FROM #t

Fuentes: Microsoft, MSDN

Chapter 11

Creacin de ndices en tablas


Es posible crear uno o ms ndices en una tabla a fin de acelerar el proceso de recuperacin de datos. Los ndices son transparentes para los usuarios que acceden a los datos de esa tabla; SQL Server decide automticamente cundo usar los ndices creados para las tablas. En este captulo se trata lo siguiente:

Introduccin general a los ndices y algunas indicaciones sobre cundo deben usarse Creacin de ndices para una tabla Uso de ndices agrupados y no agrupados Especificacin de opciones de ndices Omisin de ndices Determinacin de los ndices que existen en una tabla

Definicin de ndice Los ndices ayudan a SQL Server a localizar datos. Aceleran el proceso de recuperacin de informacin indicando a SQL Server la posicin que ocupan los datos de una columna de tabla en el disco. Las tablas pueden tener ms de un ndice. Los ndices son transparentes para los usuarios. SQL no incluye ninguna sintaxis para hacer referencia a un ndice en una consulta. Slo es posible crear u omitir ndices de una tabla; SQL Server decide si usarlos o no para cada una de las consultas ejecutadas para esa tabla. A medida que los datos de una tabla van cambiando con el tiempo, SQL Server puede cambiar los ndices de la tabla de modo que reflejen esas modificaciones. Tambin estos cambios son transparentes para los usuarios, SQL Server lleva a cabo esta tarea por su cuenta. SQL Server admite los siguientes tipos de ndices:

Indices compuestos : estos ndices abarcan ms de una columna. Este tipo de ndice se usa cuando es ms conveniente buscar dos o ms columnas como unidad, debido a la relacin lgica existente entre ellas.

Indices nicos : estos ndices no permiten que dos filas de las columnas especificadas tengan el mismo valor. SQL Server verifica si existen valores duplicados cuando se crea el ndice (si ya existen datos) y cada vez que se aaden datos. Indices agrupados o no agrupados : los ndices agrupados obligan a SQL Server a que ordene y vuelva a ordenar continuamente las filas de la tabla de modo que su orden fsico sea siempre el mismo que el orden lgico (o indexado). Slo se permite un ndice agrupado por tabla. Los ndices no agrupados no requieren que el orden fsico de las filas sea el mismo que el orden indexado. Todos los ndices no agrupados pueden proporcionar acceso a los datos con un criterio de ordenacin diferente.

Estos tipos de ndices se describen con mayor detalle ms adelante en este captulo. Comparacin de las dos formas de creacin de ndices Es posible crear ndices en las tablas usando la instruccin create index (descrita en este captulo), o bien usando las restricciones de integridad unique o primary key del comando create table . Sin embargo, estas restricciones de integridad estn limitadas de las siguientes formas:

No podr crear ndices no nicos. No podr usar las opciones proporcionadas por el comando create index para adaptar el funcionamiento de los ndices. Slo podr omitir estos ndices como una restriccin usando la instruccin alter table .

Si la aplicacin que usa requiere estas funciones, deber crear los ndices mediante create index . De lo contrario, las restricciones de integridad unique o primary key ofrecen una forma ms sencilla de definir un ndice para una tabla. Para obtener informacin sobre las restricciones unique y primary key , consulte el Captulo 7, "Creacin de bases de datos y tablas".

Indicaciones para el uso de ndices Los ndices aceleran la recuperacin de datos. La inclusin de un ndice en una columna supone con frecuencia la diferencia entre una respuesta inmediata a una consulta y una larga espera. Si esto es as, sera lgico suponer que lo adecuado es incluir un ndice en cada columna. La razn ms importante por la que esto no es as, es que la construccin de un ndice lleva tiempo y ocupa espacio de almacenamiento. Por ejemplo, tenga en cuenta que los ndices no agrupados se vuelven a crear de forma automtica cuando un ndice agrupado se reconstruye. Otra razn es que la insercin, eliminacin o actualizacin de datos de columnas indexadas lleva ms tiempo que el precisado por las no indexadas. Sin embargo, este coste se ve compensado con creces gracias a la enorme mejora que supone el uso de ndices para el rendimiento de los procesos de recuperacin. A continuacin se indican algunas directrices sobre cundo utilizar ndices:

Si planea realizar inserciones manuales en la columna IDENTITY, cree un ndice nico a fin de garantizar que las inserciones no asignen un valor que ya se haya usado. Una columna a la que se acceda con frecuencia segn criterios de ordenacin, es decir, una especificada en la clusula order by , probablemente debera indexarse a fin de que SQL Server pudiera beneficiarse del orden indexado. Las columnas que se usan de forma regular en combinaciones siempre deberan indexarse, dado que el sistema puede llevar a cabo la combinacin con mayor rapidez si las columnas estn ordenadas segn criterios de ordenacin. La columna que almacena la clave primaria de la tabla tiene con frecuencia un ndice agrupado, especialmente si se combina a menudo con columnas de otras tablas (no olvide que slo hay un ndice agrupado por tabla). Una columna en la que se realizan bsquedas frecuentes de mrgenes de valores puede ser una opcin adecuada para la asignacin de un ndice agrupado. Una vez encontrada la fila con el primer valor del

margen, se garantiza que las filas con los valores subsiguientes sern fsicamente adyacentes. Un ndice agrupado no ofrece ventajas tan importantes para las bsquedas sobre valores nicos. Existen algunos casos en los que los ndices no son tiles:

Las columnas a las que casi nunca o nunca se hace referencia en las consultas no obtienen ninguna ventaja de los ndices, puesto que el sistema casi nunca o nunca tiene que buscar filas basndose en los valores de dichas columnas. Las columnas que slo tienen dos o tres valores, como varn y mujer, o s y no, tampoco se benefician de los ndices.

Si el sistema tiene que buscar en una columna no indexada, lo hace examinando las filas una a una. El tiempo que se tarda en llevar a cabo este tipo de barrido es directamente proporcional al nmero de filas de la tabla. Creacin de ndices para acelerar la recuperacin de datos Los ndices se crean en las columnas para acelerar la recuperacin de datos. El formato ms sencillo del comando create index es: create index index_name on table_name ( column_name ) Para crear un ndice en la columna au_id de la tabla authors , el comando es el siguiente: create index au_id_ind on authors(au_id) El nombre del ndice debe cumplir con las reglas para identificadores. Los nombres de columna y tabla especifican la columna que se desea indexar y la tabla que la contiene. No es posible crear ndices en columnas que tienen los tipos de datos bit , text o image . Es necesario ser el propietario de una tabla para poder ejecutar create o drop a fin de crear u omitir un ndice. El propietario de una tabla puede crear

u omitir un ndice en cualquier momento, independientemente de que haya datos en la tabla. Es posible crear ndices en tablas de otra base de datos calificando el nombre de la tabla. Sintaxis de create index La sintaxis completa del comando create index es: create [unique] [clustered | nonclustered] index index_name on [[ database .] owner .] table_name ( column_name [, column_name ]...) [with {{fillfactor | max_rows_per_page}= x, ignore_dup_key, sorted_data, [ignore_dup_row | allow_dup_row]}] [on segment_name ] En los siguientes apartados se explican las diversas opciones del comando create index . Note: La extensin on segment_name de create index permite colocar el ndice en un segmento que apunte a un dispositivo de bases de datos especfico o a un conjunto de dispositivos de bases de datos. Antes de crear un ndice en un segmento, consulte al administrador del sistema o al propietario de la base de datos a fin de obtener una lista de los segmentos que puede utilizar. Algunos segmentos pueden estar asignados a tablas o ndices especficos por razones de rendimiento, o por otras consideraciones. Indexacin de ms de una columna: ndices compuestos Es necesario especificar uno o ms nombres de columna si se desea crear un ndice compuesto sobre los valores combinados de todas las columnas especificadas. Los ndices compuestos se usan cuando es conveniente buscar dos o ms columnas como una unidad. Por ejemplo, la tabla friends_etc tiene un ndice compuesto en pname y sname . Ponga todas las columnas que deben incluirse en el ndice compuesto segn los criterios de ordenacin dentro del parntesis despus del nombre de la tabla, como a continuacin:

create index nmind on friends_etc(pname, sname) Las columnas de un ndice compuesto no tienen que estar en el mismo orden que las columnas de la instruccin create table . El orden de pname y sname se puede invertir en la instruccin de creacin de ndices anterior. Es posible combinar hasta 16 columnas en un mismo ndice compuesto. Todas las columnas de un ndice compuesto deben estar en la misma tabla. El tamao mximo permitido de los valores de ndice combinados es de 256 bytes. Es decir, la suma de las longitudes de las columnas que componen el ndice compuesto no puede exceder de 256. Es posible especificar dos o ms nombres de columna al crear un ndice. Estas columnas, junto con la columna sensitivity , forman un ndice compuesto de los valores combinados de las columnas. Los ndices compuestos se emplean cuando es conveniente buscar dos o ms columnas como una unidad. Por ejemplo, la tabla friends_etc tiene un ndice compuesto en pname , sname y sensitivity (aadida de forma automtica por SQL Server). Cuando especifique las columnas en la instruccin create index , ponga todas las columnas que deben incluirse en el ndice compuesto, salvo sensitivity , entre parntesis segn los criterios de ordenacin despus del nombre de la tabla, como a continuacin: create index nmind on friends_etc(pname, sname) Las columnas de un ndice compuesto no tienen que estar en el mismo orden que las columnas de la instruccin create table . El orden de pname y sname podra invertirse en la instruccin de creacin de ndices anterior. SQL Server siempre aade sensitivity como la ltima columna de cada ndice. Uso de la opcin unique Un ndice nico es aqul en el que no se permite que dos filas tengan el mismo valor de ndice, incluido el valor NULL. El sistema verifica la existencia de valores duplicados cuando el ndice se crea, si ya existen datos, y realiza esta verificacin cada vez que se aaden o modifican datos con una instruccin insert o update .

La especificacin de un ndice nico slo es til cuando la unicidad es una caracterstica de los datos propiamente dichos. Por ejemplo, no es conveniente asignar un ndice nico a una columna last_name (de apellidos), puesto que es probable que haya ms de un "Smith" o "Wong" en tablas incluso de algunos centenares de filas. Sin embargo, s es adecuado asignar un ndice nico a la columna que contiene los nmeros de la seguridad social. En este caso, la unicidad es una caracterstica propia de los datos, puesto que cada persona tiene un nmero de seguridad social diferente. Adems, un ndice nico puede hacer las veces de una verificacin de integridad. Por ejemplo, la existencia de un nmero de seguridad social duplicado refleja con toda probabilidad un error en la introduccin de los datos o por parte de la administracin pblica. Si intenta crear un ndice nico en datos existentes que incluyen valores duplicados, el comando se aborta y SQL Server muestra un mensaje de error que indica el primer duplicado. No es posible crear un ndice nico en una columna que contiene valores nulos en ms de una fila; stos se consideran valores duplicados para fines de indexacin. Si intenta modificar datos que tienen asignado un ndice nico, el resultado depende de si ha usado la opcin ignore_dup_key . Consulte la seccin dedicada a las opciones de ndices ms adelante en este captulo. Es posible usar la palabra clave unique en ndices compuestos. Esto no se ha llevado a cabo para el ndice friends_etc creado anteriormente. Inclusin de columnas IDENTITY en ndices no nicos La opcin identity in nonunique index incluye de forma automtica una columna IDENTITY en las claves de ndice de una tabla para que todos los ndices creados en la tabla sean nicos. Esta opcin de base de datos hace que los ndices lgicamente no nicos sean nicos internamente y permite usarlos para procesar cursores actualizables y lecturas de nivel de aislamiento 0. La tabla ya debe contener una columna IDENTITY para que la opcin de base de datos identity in nonunique index funcione, ya sea por una instruccin

create table o al definir la opcin de base de datos auto identity como true antes de crear la tabla. Use identity in nonunique index si planea utilizar cursores y lecturas de nivel de aislamiento 0 en tablas con ndices no nicos. El ndice nico hace que el cursor se coloque en la fila correcta la siguiente vez que se efecta una operacin fetch con dicho cursor. Uso de las opciones fillfactor y max_rows_per_page Casi nunca es necesario incluir las opciones fillfactor o max_rows_per_page en la instruccin create index . Estas opciones se proporcionan para mejorar el rendimiento y slo son tiles cuando se crea un nuevo ndice sobre datos existentes.

fillfactor
Con la opcin fillfactor , el usuario puede especificar en qu medida debe llenar SQL Server cada pgina de ndice. La cantidad de espacio libre en una pgina de ndice se debe controlar porque cuando una pgina de ndice se llena una vez que se han aadido suficientes filas, el sistema debe emplear algn tiempo en dividirla a fin de dejar espacio para nuevas filas. El valor predeterminado es 0, que es el valor que se usa cuando no se especifica ningn factor de llenado. El administrador del sistema puede cambiar el valor predeterminado con el procedimiento del sistema sp_configure . Consulte la Gua de Administracin del Sistema para obtener ms informacin sobre fillfactor . Los valores vlidos de fillfactor especificados por el usuario estn entre 1 y 100. A continuacin se muestra una instruccin create index que usa la opcin fillfactor : create index postalcode_ind on friends_etc(postalcode) with fillfactor = 100

Un valor fillfactor de 100 llena completamente todas las pginas y slo es til cuando se sabe de antemano que nunca va a cambiar ninguno de los valores de ndice de la tabla.

max_rows_per_page
La opcin max_rows_per_page limita el nmero de filas que SQL Server puede incluir en cada pgina de ndice. Un valor max_rows_per_page bajo reduce la contienda de bloqueo y slo resulta til para las tablas a las que se accede con frecuencia. Los valores bajos tambin hacen que el ndice ocupe espacio. El valor predeterminado es 0, que se emplea cuando no se especifica un valor mximo. El usuario puede cambiar el valor con el procedimiento del sistema sp_relimit . Los valores max_rows_per_page especificados por el usuario estn entre 1 y 256. La siguientes instruccin create index utiliza la opcin max_rows_per_page : create index postalcode_ind on friends_etc(postalcode) with max_rows_per_page = 10 Uso de ndices agrupados o no agrupados Con un ndice agrupado, SQL Server ordena las filas de forma continuada de modo que su orden fsico sea el mismo que el orden lgico, es decir, el indexado. El nivel inferior o de hoja de un ndice agrupado contiene las pginas de datos reales de la tabla. Los ndices agrupados deben crearse antes que los no agrupados, ya que estos ltimos se reconstruyen automticamente cuando se crea un ndice agrupado. Por definicin, slo puede haber un ndice agrupado por tabla. Este se crea a menudo en la clave primaria , es decir, la columna o columnas que identifican la fila de forma nica.

Lgicamente, una clave primaria viene determinada por el diseo de la base de datos. Sin embargo, es posible definir de forma explcita las claves primarias, las claves externas y las claves comunes (pares de claves que se combinan con frecuencia) con los procedimientos del sistema sp_primarykey , sp_foreignkey y sp_commonkey . Puede mostrar informacin sobre las claves y sobre las columnas que son probables candidatos de combinacin mediante sp_helpkey y sp_helpjoins , respectivamente. Como alternativa, es posible especificar restricciones primary key con las instrucciones create table o alter table a fin de crear un ndice e imponer los atributos de clave primaria para las columnas de la tabla. Para mostrar informacin sobre las restricciones, utilice sp_helpconstraint . Para obtener una definicin de las claves primarias y externas, consulte el Captulo 15, "Disparadores: imposicin de la integridad de referencia". Para obtener informacin completa sobre los procedimientos del sistema, consulte el Manual de Referencia de SQL Server. Con un ndice no agrupado, el orden fsico de las filas no es el mismo que el indexado. El nivel de hoja de un ndice no agrupado contiene punteros hacia las filas de las pginas de datos. Ms concretamente, cada pgina hoja contiene un valor indexado y un puntero hacia la fila que contiene dicho valor. En otras palabras, un ndice no agrupado tiene un nivel adicional entre la estructura de ndice y los datos propiamente dichos. Cada uno de los hasta 249 ndices no agrupados permitidos en una tabla puede proporcionar acceso a los datos segn un criterio de ordenacin distinto. La bsqueda de datos mediante un ndice agrupado es casi siempre ms rpido que mediante un ndice no agrupado. Adems, los ndices agrupados suponen una ventaja cuando se recuperan muchas filas con valores clave contiguos, es decir, en las columnas donde se efectan bsquedas frecuentes de mrgenes de valores. Una vez que se encuentra la fila con el primer valor clave , se garantiza que las filas con valores indexados subsiguientes sern fsicamente adyacentes, y no ser necesaria ninguna bsqueda adicional. Si no se usa la palabra clave clustered ni la palabra clave nonclustered , se crea un ndice no agrupado.

A continuacin se muestra la forma de crear el ndice de la columna title_id de la tabla titles (si desea ejecutar este comando, primero debe omitir el ndice con drop index ): create clustered index titleidind on titles(title_id) Puesto que piensa que ser necesario ordenar con frecuencia las personas de la tabla friends_etc segn su cdigo postal, debera crear un ndice no agrupado en la columna postalcode de la siguiente manera: create nonclustered index postalcodeind on friends_etc(postalcode) Un ndice nico no tendra ningn sentido en este caso, puesto que es probable que algunos de sus contactos tengan el mismo cdigo postal. Un ndice agrupado no sera adecuado tampoco, puesto que el cdigo postal no es la clave primaria. El ndice agrupado de friends_etc debera ser un ndice compuesto sobre las columnas de nombre y apellidos. Para crear este ndice agrupado, primero omita el ndice no agrupado nmind : drop index friends_etc.nmind Y luego cree el ndice agrupado: create clustered index nmind on friends_etc(pname, sname) Note: Dado que el nivel inferior (o de hoja) de un ndice agrupado y sus pginas de datos son iguales por definicin, la creacin de un ndice agrupado ( clustered ) y el uso de la extensin on segment_name traslada efectivamente la tabla desde el dispositivo donde se cre hasta el segmento indicado. Consulte al administrador del sistema o al propietario de la base de datos antes de crear tablas o ndices en los segmentos; algunos segmentos pueden estar reservados por razones de rendimiento.

Especificacin de opciones de ndices Las opciones de ndices ignore_dup_key, ignore_dup_row y allow_dup_row controlan lo que ocurre cuando se crea una clave o fila duplicada con insert o update . A continuacin se muestra una tabla que indica cundo se deben usar estas opciones de ndices: Tabla 11-1: Opciones de ndices Tipo de ndice Agrupado Agrupado nico No agrupado Opciones ignore_dup_row | allow_dup_row ignore_dup_key Ninguna

No agrupado nico ignore_dup_key No agrupado nico ignore_dup_row Uso de la opcin ignore_dup_key Si intenta insertar un valor duplicado en una columna que tiene un ndice nico, el comando se cancela. Es posible evitar que se cancele una transaccin grande incluyendo la opcin ignore_dup_key con un ndice unique . El ndice unique puede ser agrupado o no agrupado. Cuando se comienza la introduccin de datos, cada intento de insercin de una clave duplicada se cancela, con un mensaje de error. Las claves no duplicadas se insertan de la forma habitual. Note: Si intenta ejecutar una instruccin update que crea una clave duplicada, la actualizacin se cancela. Tras la cancelacin, todas las transacciones que estaban activas en ese momento pueden continuar como si la actualizacin con update no hubiese tenido lugar. No se puede crear un ndice nico en una columna que ya incluye valores duplicados, independientemente de que ignore_dup_key est definida. Si lo intenta, SQL Server imprime un mensaje de error y una lista de valores duplicados. Hay que eliminar los duplicados antes de crear un ndice nico en la columna. A continuacin se muestra un ejemplo del uso de la opcin ignore_dup_key :

create unique clustered index phone_ind on friends_etc(phone) with ignore_dup_key Uso de las opciones ignore_dup_row y allow_dup_row ignore_dup_row y allow_dup_row son opciones para la creacin de un ndice agrupado y no nico. Estas opciones no son relevantes al crear un ndice no agrupado y no nico. Puesto que un ndice no agrupado de SQL Server anexa internamente un nmero de identificacin de fila nico, no es necesario preocuparse por las filas duplicadas, ni siquiera por los valores de datos idnticos. ignore_dup_row y allow_dup_row se excluyen mutuamente. Si se define allow_dup_row , es posible crear un ndice nuevo no nico y agrupado en una tabla que incluye filas duplicadas y, a continuacin, crear filas duplicadas subsiguientes con insert o update . Si alguno de los ndices de la tabla es nico, el requisito de unicidad, que es el requisito ms restrictivo, prevalece sobre la opcin allow_dup_row . Por tanto, allow_dup_row slo se aplica a tablas con ndices no nicos. No puede usar esta palabra clave si hay un ndice agrupado nico en alguna de las columnas de la tabla. La opcin ignore_dup_row se utiliza para eliminar los duplicados de un lote de datos. Cuando se introduce una fila duplicada, esta fila se ignora y el comando insert en cuestin se cancela, con un mensaje de error informativo. Las filas no duplicadas se insertan de la forma habitual. La opcin ignore_dup_row se aplica slo a las tablas con ndices no nicos: no puede usar esta palabra clave si hay un ndice nico en alguna de las columnas de la tabla. Note: Si intenta ejecutar una instruccin update que cree una fila duplicada, la actualizacin se cancelar. Tras la cancelacin, las transacciones que estaban activas en ese momento pueden continuar como si la actualizacin no hubiese tenido lugar.

Esta tabla ilustra la forma en que allow_dup_row y ignore_dup_row afectan a los intentos de creacin de un ndice agrupado no nico en una tabla que incluye filas duplicadas y a los intentos de introduccin de filas duplicadas en una tabla. Tabla 11-2: Opciones de filas duplicadas en ndices Opcin Ninguna opcin definida Duplicados existentes Introduccin de duplicados

El comando create El comando de introduccin index no se ejecuta de filas duplicadas no se de forma correcta. ejecuta de forma correcta. El comando se ejecuta de forma correcta. El comando se ejecuta de forma correcta.

allow_dup_row definida

ignore_dup_row<Default Para Font> definida

Se crea el ndice, Se aceptan todas las filas, pero las filas excepto las duplicadas; duplicadas se mensaje de error. Consulte eliminan; mensaje de la advertencia anterior. error.

Uso de la opcin sorted_data La opcin sorted_data acelera la creacin de un ndice cuando los datos de la tabla ya estn clasificados segn criterios de ordenacin, por ejemplo, cuando se ha usado bcp para copiar datos que ya se han ordenado en una tabla vaca. La velocidad aumenta de forma considerable en las tablas de gran tamao y es varias veces superior en las tablas de ms de un gigabyte. Esta opcin puede utilizarse con cualquier otra opcin create index sin ningn efecto sobre su funcionamiento. Si se especifica sorted_data , pero los datos no estn ordenados, aparece un mensaje de error y el comando se aborta. Esta opcin agiliza la creacin de ndices slo para ndices agrupados o ndices no agrupados nicos. Sin embargo, la creacin de un ndice no agrupado y no nico tendr xito siempre que no haya filas con claves duplicadas. Si existen filas con claves duplicadas, aparece un mensaje de error y el comando se aborta.

Uso de la opcin on segment_name La clusula on segment_name permite especificar el nombre del segmento de base de datos donde debe crearse el ndice. Es posible crear un ndice no agrupado en un segmento distinto del de las pginas de datos. Por ejemplo: create index titleind on titles(title) on seg1 Omisin de ndices El comando drop index se usa para quitar un ndice de la base de datos. Su sintaxis es: drop index table_name . index_name [, table_name . index_name ]... Cuando se ejecuta este comando, SQL Server quita los ndices especificados de la base de datos, dejando libre el espacio de almacenamiento. Slo el propietario del ndice puede omitirlo. El permiso drop index no puede transferirse a otros usuarios. El comando drop index no puede usarse en ninguna de las tablas del sistema de la base de datos master ni en la base de datos de usuario. Es posible que quiera omitir un ndice si no se usa en la mayora de las consultas o en ninguna. Para omitir el ndice phone_ind de la tabla friends_etc , el comando es: drop index friends_etc.phone_ind Determinacin de los ndices que existen en una tabla Para ver los ndices que existen en una tabla, es posible usar el procedimiento del sistema sp_helpindex . A continuacin se muestra un informe sobre la tabla friends_etc : sp_helpindex friends_etc

index_name index_description index_keys -------------- ---------------------------- ------------nmind clustered located on default pname, sname postalcode_ind nonclustered located on default postalcode postalcodeind nonclustered located on default postalcode (3 rows affected, return status = 0) sp_help tambin informa sobre los ndices de una tabla. Actualizacin de estadsticas sobre los ndices El comando update statistics ayuda a SQL Server a tomar las mejores decisiones sobre qu ndices debe usar cuando procesa una consulta, proporcionndole informacin actualizada sobre la distribucin de los valores clave de los ndices. Este comando debe utilizarse cuando se han aadido, modificado o eliminado grandes cantidades de datos de una columna indexada. El permiso para ejecutar el comando update statistics est asignado de forma predeterminada al propietario de la tabla, y no es transferible. Su sintaxis es: update statistics table_name [ index_name ] Si no se especifica un nombre de ndice, el comando actualiza las estadsticas de distribucin de todos los ndices de la tabla indicada. Si se especifica el nombre de un ndice, slo se actualizan las estadsticas de ese ndice. Se pueden buscar los nombres de los ndices con el procedimiento del sistema sp_helpindex . Este procedimiento toma como parmetro un nombre de tabla. A continuacin se muestra cmo enumerar los ndices de la tabla authors : sp_helpindex authors index_name index_description index_keys

---------- ----------------- -----------------auidind clustered, unique au_id aunmind nonclustered au_lname, au_fname (2 rows affected) Para actualizar las estadsticas de todos los ndices, escriba: update statistics authors Para actualizar las estadsticas slo del ndice de la columna au_id , escriba: update statistics authors auidind Dado que Transact-SQL no requiere que los nombres de ndice sean nicos en una base de datos, se debe indicar el nombre de la tabla a la que est asociado el ndice. SQL Server ejecuta update statistics de forma automtica cuando se crea un ndice en los datos existentes.

Вам также может понравиться