Estuve probando los comentarios escritos en esos artículos del año 2002
escritos para el SQL Server 2000 en un SQL Server 2005.
Se nota bastante las mejoras introducidas en el motor del 2005.
Lo mas problemático a mi criterio en lo que respecta al articulo de
rendimiento es el concepto vertido.
Si vemos la version ligeramente modificada que les paso, verán que es mas
eficiente la versión con tablas temporales 43% de IO que la de tabla
derivada 57% de IO justamente debido al primary key clustered que le cree a
la tabla temporal.
Ejecutando lo mismo en el SQL Server 2000 me da 62% (temporales) versus 38%
con la tabla derivada coincidiendo con la información del articulo.
Por lo tanto debemos ser cuidadosos al respecto y tomar en cuenta los
conceptos. Si los volúmenes crecieran bastante creo que la de tablas
derivadas afectaría mas al buffer manager si se requiriera algún tipo de
almacenamiento intermedio para proseguir con la resolución de la query. Si
pudiera simplificarlo y usar el "flujo de filas" internamente quiza sea
mucho mejor las tablas derivadas.
El uso de Common Table Expresions o vistas es casi exactamente equivalente
al de tablas derivadas. Aquellos que hemos sufrido el problema de las vistas
de vistas me entenderán.
Justamente en este tipo de cosas es donde las tablas temporales pueden
aportar mejoras por sobre las variables tablas y las tablas derivadas en
ocasiones pueden ser algo peores como en este caso pero, debe tenerse en
cuenta que las tablas temporales provocan mas recompilaciones y que las
tablas derivadas pueden permitir mecanismos de simplificación y por lo tanto
mejores rendimientos que las tablas temporales, sobre todo en las nuevas
versiones del motor.
Por lo tanto prefiero analizarlo y comparar.
En tu caso, habría que analizar si la TEMPDB del equipo que indicas si tenia
el tamaño adecuado y estaba configurada adecuadamente quiza no se producían
los IOstalls.
Me parece perfecto que se haya solucionado con la tabla derivada.
Les paso los códigos para que puedan compararlos ustedes.
.
---------------------------------
-- sin tablas temporales
---------------------------------
SELECT
C.CategoryID,
C.CategoryName,
P.ProductName,
P.UnitPrice,
CT.Category_Count
FROM Categories C
INNER JOIN Products P
ON C.CategoryID = P.CategoryID
INNER JOIN (
SELECT
C.CategoryID,
COUNT(*) AS Category_Count
FROM
Categories C
INNER JOIN Products P
ON C.CategoryID = P.CategoryID
GROUP BY
C.CategoryID--,C.CategoryName
)CT
ON C.CategoryID = CT.CategoryID
ORDER BY
C.CategoryName;
---------------------------------
-- Con CTE
---------------------------------
With
CT AS
(
SELECT
C.CategoryID,
COUNT(*) AS Category_Count
FROM
Categories C
INNER JOIN Products P
ON C.CategoryID = P.CategoryID
GROUP BY
C.CategoryID--,C.CategoryName
)
SELECT
C.CategoryID,
C.CategoryName,
P.ProductName,
P.UnitPrice,
CT.Category_Count
FROM Categories C
INNER JOIN Products P
ON C.CategoryID = P.CategoryID
INNER JOIN CT
ON C.CategoryID = CT.CategoryID
ORDER BY
C.CategoryName
---------------------------------
-- Con tablas temporales
---------------------------------
CREATE TABLE #Temp_Example (
[CategoryID] INT NOT NULL primary key clustered,
[Category_Count] INT NOT NULL,
)
INSERT INTO #Temp_Example (
CategoryID,
Category_Count
)
SELECT
C.CategoryID,
COUNT(*) AS Category_Count
FROM Categories C
INNER JOIN Products P
ON C.CategoryID = P.CategoryID
GROUP BY
C.CategoryID --,C.CATEGORYNAME
order by
C.CategoryID
SELECT
C.CategoryID,
C.CategoryName,
P.ProductName,
P.UnitPrice,
#Temp_Example.Category_Count
FROM Categories C
INNER JOIN Products P
ON C.CategoryID = P.CategoryID
INNER JOIN #Temp_Example
ON C.CategoryID = #Temp_Example.CategoryID
ORDER BY
C.CategoryName
DROP TABLE #Temp_Example
--------------------------------
Atte.
Ing. Jose Mariano Alvarez
SQL Total Consulting
2008/11/14 Mariano Minoli <[EMAIL PROTECTED]>
> Hola Mariano !
>
> Yo antes de esta auditoría nunca me había parado a pensarlo, ni lo había
> visto documentado.
>
> Cuando llegué al entorno los desarrolladores habían detectado que había
> una consulta que, cuando pasaba determinada cantidad de registros (800.000
> si no recuerdo mal) quedaba ejecutándose durante horas con muy poca
> utilización de recursos en el servidor (coloquialmente se moría :) ).
>
> La sentencia que se moría era esta:
>
> INSERT INTO #la_tabla_temporal
>
> SELECT campos....
>
> FROM tabla_externa
>
> WHERE EXISTS (
>
> SELECT #otra_tabla_temporal.uncampo
>
> FROM #otra_tabla_temporal
> WHERE #otra_tabla_temporal.id = tabla_externa.id)
>
> Les pedí a los desarroladores que eviten las tablas temprales usando
> estas recomentaciones:
>
>
>
> http://www.sql-server-performance.com/articles/per/derived_temp_tables_p1.aspx
>
>
> http://www.sql-server-performance.com/articles/per/derived_temp_tables_p2.aspx
>
> Y conseguimos un stored que (si bien consume sus recursos) no presenta el
> comportamiento de "quedarse pensando" 1 hora.
>
> Tenes razón respecto a la nomenclatura, en Oracle les llaman in-line views
> o queries, aca son Tablas Derivadas, básicamente un select de un select:
>
> SELECT * FROM (SELECT * FROM categories) dt_categories
>
>
>
> Un saludo !!!
>
>
>
> Mariano Minoli
>
> ------------------------------
> *From:* Jose Mariano Alvarez <[EMAIL PROTECTED]>
> *To:* [EMAIL PROTECTED]
> *Sent:* Friday, November 14, 2008 4:22:18 AM
> *Subject:* [dbms] Tablas temporales
>
> Mariano:
>
> No se que cambios hicieron exactamente y si te referis a una tabla
> derivada.
>
> Es casi exactamente lo mismo una tabla derivada que una tabla temporal.
> Por otro lado dependiendo del caso (#registros y uso de los mismos) una
> tabla temporal puede acelerar las cosas o enlentecerlas respecto de otras
> alternativas.
>
> Una tabla temporal puede tener indices por ejemplo.
>
> Si remplazaros todo el proceso (multiples pasadas sobre la temporal) por
> una query es otra cosas
>
> Saludos
>
> --------------------------------
> Atte.
> Ing. Jose Mariano Alvarez
> SQL Total Consulting
>
>
> 2008/11/12 Mariano Minoli <[EMAIL PROTECTED]>
>
>> Hola Sonia,
>>
>> Solo un comentario respecto a las tablas temporales: cuidado con la
>> cantidad de datos que cargas allí.
>>
>> Hace poco hicimos una auditoría de performance en un sistema que cargaba
>> + de 900.000 de registros en una tabla temporal y luego comenzaba a hacer
>> consultas sobre la misma. El servidor se moría. Reemplazamos la tabla
>> temporal por un inline query y quedo funcionando bien.
>> Un saludo,
>>
>>
>> Mariano Minoli
>>
>> ------------------------------
>> *From:* silvana quiroga <[EMAIL PROTECTED]>
>> *To:* [EMAIL PROTECTED]
>> *Sent:* Wednesday, November 12, 2008 2:33:09 PM
>> *Subject:* [dbms] Tablas temporales
>>
>> No coinciden. Se crea una por cada conexión. Si tu tabla se llama
>> #table, fijate que en las tablas del sistema te crea la tabla
>> #table_00000..., #table_00001, etc. es decir, le agrega un número al final
>> para diferenciarlas.
>>
>> 2008/11/12 Sonia Perez Peña <[EMAIL PROTECTED]>
>>
>>>
>>>
>>>
>>>
>>> -----Mensaje original-----
>>> *De:* Sonia Perez Peña
>>> *Enviado el:* miércoles, 12 de noviembre de 2008 7:54
>>> *Para:* '[email protected]'
>>> *Asunto:* Tablas temporales
>>>
>>>
>>>
>>> Hola amigos, que riesgos puedo tener al utilizar tablas temporales
>>> #Table, se que estas se crean en la TEMPDB, por la que tengo que competir
>>> con el espacio de memoria de la TEMPDB., fuera de esto que otra cosa, se que
>>> cuando un usuario se desconecta, pero mi preocupación es cuando n usuarios,
>>> pueden coincidir con la construcción de la misma. ¿????
>>>
>>>
>>>
>>>
>>>
>>> Gracias.
>>>
>>>
>>>
>>>
>>>
>>
>>
>>
>
>