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

Tablas virtuales en el SQL Server

Introducción
En el mundo de las bases de datos es muy común la utilización de tablas
temporales. A pesar de que todo el mundo sabe que este tipo de estructuras
ralentizan el funcionamiento de nuestras consultas, los programadores no pueden
evitar recurrir a ellas porque muchas veces facilitan la resolución de problemas.
Almacenar datos para usarlos posteriormente, guardar resultados parciales,
analizar grandes cantidades de filas. Hay muchos casos en los que podemos
necesitar estas tablas temporales, ¡Pero hay que utilizarlas correctamente! Primer
consejo: no usar tablas temporales
El primer consejo que tenemos que seguir a la hora de trabajar con tablas
temporales es bien sencillo: no usarlas. ¿Y por qué no? Pues hay un montón de
razones que iremos viendo a lo largo de este texto, pero para empezar veamos en
que se traduce el utilizar una tabla temporal en SQL Server:

 Las tablas temporales se crean en tempdb, y al crearlas se producen varios


bloqueos sobre esta base de datos como por ejemplo en las tablas
sysobjects y sysindex. Los bloqueos sobre tempdb afectan a todo el
servidor.
 Al crearlas es necesario que se realicen accesos de escritura al disco ( no
siempre si las tablas son pequeñas)
 Al introducir datos en las tablas temporales de nuevo se produce actividad
en el disco, y ya sabemos que el acceso a disco suele ser el "cuello de
botella" de nuestro sistema
 Al leer datos de la tabla temporal hay que recurrir de nuevo al disco.
Además estos datos leídos de la tabla suelen combinarse con otros.
 Al borrar la tabla de nuevo hay que adquirir bloqueos sobre la base de
datos tempdb y realizar operaciones en disco.
 Al usar tablas temporales dentro de un procedimiento almacenado
perdemos la ventaja de tener compilado el plan de ejecución de dicho
procedimiento almacenado y se producirán recompilaciones más a menudo.
Lo mismo pasará cuando el SQL Server intenta reutilizar el plan de
ejecución de una consulta parametrizada. Si en la consulta tenemos una
tabla temporal difícilmente se reutilizará dicho plan de ejecución.

Vistos estos problemas creo que no hace falta repetir nuestro prime consejo. ¿Y
qué podemos hacer entonces?
En vez de tablas temporales podemos mejorar nuestro código para que no sean
necesarias, podemos usar subconsultas (normalmente usar una subconsulta
mejora drásticamente el rendimiento respecto a usar tablas temporales), usar
tablas permanentes, usar tablas derivadas.
Hay que recordar siempre que cualquier alternativa es buena si evitamos usar
tablas temporales (¡cursores excluidos por supuesto!)
De todos modos si alguna vez tenemos que usarlas es mejor conocerlas bien, así
que vamos a ello. Tipos de tablas temporales
Las tablas temporales son de dos tipos en cuanto al alcance la tabla. Tenemos
tablas temporales locales y tablas temporales globales.
#locales: Las tablas temporales locales tienen una # como primer carácter en su
nombre y sólo se pueden utilizar en la conexión en la que el usuario las crea.
Cuando la conexión termina la tabla temporal desaparece.
##globales Las tablas temporales globales comienzan con ## y son visibles por
cualquier usuario conectado al SQL Server. Y una cosa más, estás tablas
desaparecen cuando ningún usuario está haciendo referencias a ellas, no cuado
se desconecta el usuario que la creo.
Temp Realmente hay un tipo más de tablas temporales. Si creamos una tabla
dentro de la base de datos temp es una tabla real en cuanto a que podemos
utilizarla como cualquier otra tabla en cualquier base de datos, y es temporal en
cuanto a que desaparece en cuanto apagamos el servidor.
Funcionamiento de tablas temporales
Crear una tabla temporal es igual que crear una tabla normal. Veámoslo con un
ejemplo:

CREATE TABLE #TablaTemporal (Campo1 int, Campo2 varchar(50))

Y se usan de manera habitual.

INSERT INTO #TalbaTemporal VALUES (1,'Primer campo')


INSERT INTO #TalbaTemporal VALUES (2,'Segundo campo')
SELECT * FROM #TablaTemporal

Como vemos no hay prácticamente limitaciones a la hora de trabajar con tablas


temporales (una limitación es que no pueden tener restricciones FOREING
KEY). Optimizar el uso de tablas temporales
El uso que les podemos dar a este tipo de tablas es infinito, pero siempre teniendo
en cuenta unas cuantas directivas que debemos seguir para que ralenticen
nuestro trabajo lo menos posible.
Por ejemplo no es mala costumbre crear las tablas temporales con comandos DDL
como en el ejemplo anterior (CREATE TABLE) y luego rellenarlas comandos
INSERT o con INSERT INTO. Es cierto que eso mismo lo podemos lograr en un
único paso con SELECT INTO, pero esta opción es peor porque los bloqueos que
se adquieren sobre objetos del sistema duran más tiempo.
Como siempre es mejor pedir los campos que queremos y no poner el típico
SELCT * FROM... De la misma manera es muy recomendable cualificar las filas
que queremos y no tener filas que no vamos a utilizar en tablas temporales.
Otra buena costumbre es borrar nosotros nuestras tablas. Sí que es cierto que al
acabar la conexión las tablas temporales locales desaparecen, pero si tenemos un
conjunto de sentencias largo y creamos una tabla temporal al principio y no la
vamos a utilizar en el resto del tiempo no tiene sentido tener esa tabla ahí
ocupando espacio y memoria.
Si las tablas temporales son grandes una opción para aumentar el rendimiento es
crear un índice que nos ayude a recuperar los datos de esa tabla (para tablas
pequeñas es un gasto inútil porque nunca se usarán los índices).
Colocar la base de datos tempdb en un disco dedicado solo para esta función
aumentará el rendimiento global del sistema si se hace un uso intensivo de tablas
temporales.
Y por último pero no menos importante, no creéis tablas temporales dentro de
transacciones ni dentro de triggers. creedme que la concurrencia de vuestra base
de datos sufrirá mucho si lo hacéis. Variables de tabla
Con SQL Server 2000 podemos declarar variables de tipo table. Este tipo de
variables tienen una serie de ventajas sobre las tablas temporales por lo que
siempre que podamos escogeremos usar variables de tabla frente a tablas
temporales. Usar variables temporales es sencillo:

DECLARE @VariableTabla TABLE (Campo1 int, Campo2 char(50))


INSERT INTO @VariableTabla VALUES (1,'Primer campo')
INSERT INTO @VariableTabla VALUES (2,'Segundo campo')
SELECT * FROM @VariableTabla

Ventajas que encontraremos al usar variables de tipo tabla:

 Tienen un ámbito bien definido. El procedimiento almacenado, la función o


el batch en el que se declaran.
 Las variables de tipo tabla producen menos recompilaciones de los
procedimientos almacenados en los que se encuentran que si utilizamos
tablas temporales.
 Las variables de tabla no necesitan de bloqueos ni de tantos recursos como
las tablas temporales.

Pero también tienen inconvenientes:


 No podemos cambiar la definición de la tabla una vez declarada
 No podemos utilizar índices que no sean agrupados
 No se pueden utilizar en INSERT INTO ni en SELECT INTO
 No podemos utilizar funciones en las restricciones

Si ponemos en una balanza las ventajas y los inconvenientes vemos que en


general es mejor utilizar las variables de tipo tabla que las tablas temporales. Solo
en el caso de tener gran cantidad de datos en una tabla temporal y si la vamos a
usar varias veces es preferible la opción de tablas temporales porque en ellas
podemos definir índices. Un ejemplo
Todo esto está muy bien, pero como siempre lo mejor es ver un ejemplo en el que
podamos ver que merece la pena el esfuerzo de reprogramar nuestro código para
no usar tablas temporales.
Vamos a ver un ejemplo simple y alejado de la realidad pero que ilustre lo que
queremos explicar en este texto. Vamos a utilizar la base de datos Northwind.
En esta base de datos los pedidos se envían a través de tres compañías de
trasnportes: Speedy Express(1), United Package(2) y Federal Shipping(3). La
compañía Federal Shipping nos oferta realizar todos los envíos que hacemos a
través de United Package al precio fijo de 10$.
Decidimos que este ahorro merece la pena y vamos a cambiar en nuestra base de
datos todos los pedidos abiertos que tienen que ser enviados por United Package
para que sean enviados a través de Federal Shipping.
Para hacer esta actualización de los datos tenemos varias opciones. Vamos a
comparar tres formas de hacerlo.
Metodo 1: Tablas temporales

declare @st datetime


SET @st =getdate()
CREATE TABLE #Actualizar (OrderId int, ShipVia int, Freight money)
INSERT INTO #Actualizar SELECT OrderID, ShipVia, Freight
FROM Orders WHERE ShipVia=2 AND ShippedDate IS NULL
UPDATE Orders SET ShipVia=3, Freight=10 WHERE OrderID IN
(SELECT OrderID FROM #Actualizar)DROP TABLE #Actualizar
PRINT 'Operacion completada en: ' + RTRIM(cast(datediff(ms,@st,getdate()) as
char(10)))
+ ' milisegundos'

Y obtenemos como resultado:


(11 filas afectadas)
(11 filas afectadas)
Operacion completada en: 140 milisegundos

Metodo 1: Variables tipo Tabla

DECLARE @st datetime


SET @st =getdate()
DECLARE @Actualizar TABLE(OrderId int, ShipVia int, Freight money)
INSERT INTO @Actualizar SELECT OrderID, ShipVia, Freight
FROM Orders WHERE ShipVia=2 AND ShippedDate IS NULL
UPDATE Orders SET ShipVia=3, Freight=10 WHERE OrderID IN
(SELECT OrderID FROM @Actualizar)
PRINT 'Operacion completada en: ' + rtrim(cast(datediff(ms,@st,getdate()) AS
char(10)))
+ ' milisegundos'

Y en este caso el resultado es:

(11 filas afectadas)


(11 filas afectadas)
Operacion completada en: 73 milisegundos

Metodo 1: Sin Tablas temporales

DECLARE @st datetime


SET @st =getdate()
UPDATE Orders SET ShipVia=3, Freight=10 WHERE OrderID IN
(SELECT OrderID FROM Orders WHERE ShipVia=2 AND ShippedDate
IS NULL)
PRINT 'Operacion completada en: ' + rtrim(cast(datediff(ms,@st,getdate()) AS
char(10)))
+ ' milisegundos'

Y por último obtenemos:


(11 filas afectadas)
Operacion completada en: 50 milisegundos

Desde luego este ejemplo no es significativo, y en cada caso hay que estudiar la
situación y comparar los resultados obtenidos en un entorno de trabajo para saber
cual es la mejor opción, pero de todos modos espero que esto os sirva al menos
para conocer un poco mejor a las "tablas temporales".

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