2009-05-13 48 views
26

Me he estado preguntando sobre tablas temporales en sp's y cómo todo eso puede afectar la concurrencia. SP realizado en un servidor MSSQL 08.Tablas temporales en procedimientos almacenados

Si tengo un SP, donde se crea una tabla temporal y colocarlo de nuevo como esto:

BEGIN 

CREATE TABLE #MyTempTable 
(
    someField int, 
    someFieldMore nvarchar(50) 
) 

... Use of temp table here 
... And then.. 

DROP TABLE #MyTempTable 

END 

Este SP se llamará muy, muy a menudo, así que mi pregunta es ¿puede haber alguna producirse problemas de concurrencia aquí?

Respuesta

28

Nope. Se crearán instancias independientes de la tabla temporal para cada conexión.

+0

Está bien eso es también lo que pensaba .. me puse nervioso porque estaba usando el Analizador de consultas y construir una tabla temporal y fue capaz de llamarlo de nuevo más tarde cuando no lo dejé caer. Pero a la luz de su publicación intenté abrir una nueva consulta y traté de llamar desde allí sin éxito y ahora estoy tranquilo de nuevo :) –

+0

Pero en cuanto al rendimiento, hay importantes problemas de simultaneidad. – tpower

+1

@tpower: Mi comprensión de OP era principalmente sobre la modificación de estado compartido y problemas de subprocesos. Es obvio que el rendimiento se verá afectado. –

17

Quizás.

Las tablas temporales con el prefijo # (# ejemplo) se guardan por sesión. Entonces, si su código vuelve a llamar al procedimiento almacenado mientras se está ejecutando otra llamada (por ejemplo, hilos de fondo), la llamada de creación fallará porque ya está allí.

Si está realmente preocupado utilizar una variable de tabla en lugar

DECLARE @MyTempTable TABLE 
(
    someField int, 
    someFieldMore nvarchar(50) 
) 

Este será específico para el "ejemplo" de esa llamada al procedimiento almacenado.

+2

No puede reutilizar la sesión SQL, sin importar lo que el cliente intente hacer. – gbn

+0

"(# ejemplo) se guardan por sesión" ¿Y las sesiones se basan en una conexión? –

+0

Bien, gracias por esa aclaración gbn –

7

No es realmente y estoy hablando de SQL Server. La tabla temporal (con el número único) existe y es visible dentro del alcance que se crea (límite de alcance). Cada vez que llama a su procedimiento almacenado crea un nuevo ámbito y, por lo tanto, esa tabla temporal solo existe en ese ámbito. Creo que las tablas temporales también son visibles para los procedimientos almacenados y udfs que se llaman dentro de ese alcance también. Sin embargo, si usa doble libra (##) se vuelven globales en su sesión y, por lo tanto, visibles para otros procesos de ejecución como parte de la sesión en la que se crea la tabla temporal, y tendrá que pensar si se puede acceder a la tabla temporal al mismo tiempo es deseable o no.

-1

La base de datos utiliza el mismo candado para todas las tablas #temp, por lo que si está utilizando mucho obtendrá problemas de interbloqueo. Es mejor usar variables de tabla @ para concurrencia.

+1

-1 Lo de bloqueo no ha sido cierto desde SQL Server 6.5 –

-1

Utilice las tablas @temp siempre que sea posible, es decir, solo necesita una clave principal y no necesita acceder a los datos de un proceso almacenado subordinado.

Use las tablas #temp si necesita acceder a los datos de un proceso almacenado subordinado (es una variable global maligna a la cadena de llamadas del proceso almacenado) y no tiene otra forma limpia de pasar los datos entre los procesos almacenados. También utilizarlo si necesita un índice secundario (aunque, en realidad se pregunta si se trata de una mesa #temp si necesita más de un índice)

Si lo hace, siempre declaran su mesa #temp en la parte superior de la función. SQL forzará una recompilación de su proceso almacenado cuando vea la declaración de creación de tabla ... por lo tanto, si tiene la declaración de la tabla #temp en el medio del proceso almacenado, el proceso almacenado debe detener el procesamiento y la recompilación.

+1

-1 No, los objetos temporales (tablas y variables) generalmente se almacenan en caché en SQL Server 2005 y posterior, por lo que se evita la recompilación. Consulte http://sqlblog.com/blogs/paul_white/archive/2012/08/17/temporary-object-caching-explained.aspx y http://technet.microsoft.com/es-us/library/cc966545.aspx por ejemplo –

0

Según los libros de SQL Server 2008 Puede crear tablas temporales locales y globales. Las tablas temporales locales son visibles solo en la sesión actual, y las tablas temporales globales son visibles para todas las sesiones.

'#table_temporal

' ## table_global

Si se crea una tabla temporal local en un procedimiento almacenado o una aplicación que se puede ejecutar al mismo tiempo por varios usuarios, el motor de base debe ser capaz para distinguir las tablas creadas por los diferentes usuarios. El Motor de base de datos hace esto agregando internamente un sufijo numérico a cada nombre de tabla temporal local.

Entonces no hay ningún problema.

2

Para todos aquellos que recomiendan utilizar variables de tabla, tenga cuidado al hacerlo. La variable de tabla no puede indexarse ​​mientras que una tabla temporal puede ser. Una variable de tabla es mejor cuando se trabaja con pequeñas cantidades de datos, pero si está trabajando en conjuntos de datos más grandes (por ejemplo, 50k registros) una tabla temporal será mucho más rápida que una variable de tabla.

También tenga en cuenta que no puede confiar en un try/catch para forzar una limpieza dentro del procedimiento almacenado. ciertos tipos de fallas no pueden ser atrapadas dentro de un try/catch (por ejemplo, fallas de compilación debido a una resolución de nombre retrasada) si quiere estar realmente seguro de que necesita crear un procedimiento almacenado de wrapper que pueda hacer un try/catch del procedimiento almacenado de worker y haz la limpieza allí.

p. Ej. crear trabajador proc COMO EMPEZAR - hacer algo aquí FIN

create proc wrapper AS 
BEGIN 
    Create table #... 
    BEGIN TRY 
     exec worker 
     exec worker2 -- using same temp table 
     -- etc 
    END TRY 
    END CATCH 
     -- handle transaction cleanup here 
     drop table #... 
    END CATCH 
END 
Cuestiones relacionadas