簡體   English   中英

SQL Server中的臨時表使用情況

[英]Temporary Table Usage in SQL Server

這是一個懸而未決的問題,但我真的很想聽聽別人的意見。

我很少使用顯式聲明的臨時表(表變量或常規#tmp表),因為我認為不這樣做會導致更簡潔,可讀和可調試的T-SQL。 我還認為SQL可以比我在需要時使用臨時存儲(例如在查詢中使用派生表時)做得更好。

唯一的例外是當數據庫不是典型的關系數據庫而是星形或雪花模式時。 我知道最好先將過濾器應用於事實表,然后使用生成的臨時表從維度中獲取值。

這是普遍意見還是有人反對意見?

臨時表對於復雜的批處理過程(如報表或ETL作業)最有用。 通常,您希望在事務性應用程序中很少使用它們。

如果您正在使用涉及多個大型表(可能是報表)的連接進行復雜查詢,則查詢優化器實際上可能無法在一次命中中對此進行優化,因此臨時表在此處成為勝利 - 它們將查詢分解為一系列更簡單的一些,使查詢優化器更少有機會搞砸計划。 有時您的操作根本無法在單個SQL語句中完成,因此需要多個處理步驟才能完成工作。 我們再次討論更復雜的操作。

您還可以為中間結果創建一個臨時表,然后索引該表,甚至可能在其上放置聚簇索引以優化后續查詢。 這也可能是一種快速而骯臟的方法,可以在不允許向數據庫模式添加索引的系統上優化報表查詢。 SELECT INTO對於此類操作很有用,因為它記錄最少(因此速度很快),並且不需要對齊select和insert的列。

其他原因可能包括使用CROSS APPLY和xpath查詢從XML字段中提取數據。 通常,將其提取到臨時表中然后處理臨時表會更有效。 對於某些任務,它們也比CTE快得多,因為它們實現了查詢結果而不是重新評估查詢。

需要注意的一點是,臨時表與查詢引擎用於存儲中間連接結果的結構完全相同,因此使用它們不會有性能損失。 臨時表還允許使用set操作的多階段任務,並且在T-SQL代碼中幾乎(幾乎不是)幾乎不需要游標。

'Code Smell'是一種誇大其詞但如果我看到很多涉及臨時表的簡單操作,我會想知道發生了什么。

這真的取決於你在做什么。 我通常會盡量避免它們,但有時你需要做一些復雜的事情,需要多個步驟。 通常這超出了從表格中選擇的簡單方法。 像其他任何東西一樣,它是一個你必須知道何時使用的工具。

我同意你的觀點,我通常會讓db處理幕后的東西,但有時候它的優化是關閉的,你必須親自去做。

我將臨時表視為一種SQL代碼氣味,僅作為最后的手段使用。 如果您必須在獲得最終結果集之前緩存數據,那么它通常會向我指示錯誤的數據庫設計。

臨時表肯定有適當的用途,如果使用正確,它們不是代碼味道。 關於它們的一個好處是它們存在於tempdb中,通常設置為簡單恢復模型。 這意味着如果你正在使用臨時表來獲得它們的好處(主要是批量操作),那么與生成數據庫中的表相同的操作相比,你生成的日志量最少,這可能是在完全恢復模型中。

如果,正如另一張海報建議的那樣,您的生產數據庫位於良好的硬件上,但您的tempdb不是,請讓您的DBA移動它。 SQL Server本身使用tempdb來處理您的查詢,因此tempdb具有高性能的主頁非常重要。

表變量完全是一個不同的生物。 他們只活在記憶中。 對他們來說一個很好的用途是,如果你有一個函數,你需要使用CROSS APPLY調用查詢中的每一行。 如果該功能很昂貴,但是您可以從中獲得的結果數量很少,那么通過預先計算所有可能調用的結果(或者可能是對數據集的所有可能調用)並將其存儲在表變量,然后加入到該表變量而不是使用CROSS APPLY。

當您擁有需要一次檢索並在后續語句中反復使用的數據集時,此選項也很有用。

使這些長批處理過程更具可讀性(有時這比性能更重要)。

我也避免臨時表。 據我所知,MS SQL Server上的臨時表始終位於master數據庫的文件組中。 這意味着,雖然您的生產應用程序表很可能是在一些昂貴的高性能RAID設置上,但您的臨時表位於安裝MS SQL Server的位置,這很可能位於Program Files目錄下的C:驅動器上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM