Sql-Server-2005

執行一次子查詢/使用子查詢優化連接,無需使用臨時表

  • March 2, 2016

直到今天,我還以為我已經掌握了通過子查詢連接來優化查詢的竅門。但是我一直在嘗試優化查詢,並且一時興起嘗試了一種我認為不再需要使用的舊方法——我使用了臨時表。

慢查詢(需要 5 分鐘)…

select (columns) from big_transactions_table t inner join 

 (select (columns) from small_info_table where (conditions)) q1

on q1.key = t.key
group by (columns)

使用臨時表快速查詢…

select (columns) from small_info_table into #q1 where (conditions)

go

select (columns) from big_transactions_table t inner join #q1
on #q1.key = t.key
group by (columns)

花了14秒!

我的印像是,當您在這樣的連接中有子查詢時,SQL 引擎會先獲取數據,然後再將其與外部查詢連接。現在我不太確定。誰能告訴我為什麼執行時間有很大差異,是否有一種簡單的方法可以在不使用臨時表的情況下加快查詢速度?

我的印像是,當您在這樣的連接中有子查詢時,SQL 引擎會先獲取數據,然後再將其與外部查詢連接。

查詢優化器考慮各種物理執行策略,這些策略保證產生與原始邏輯查詢規範相同的結果。所以,不,你不能從書面形式的查詢中做出關於它將如何實際執行的一般推斷。

優化器做出的決定是基於估計的成本,這在很大程度上取決於管道每個階段預期數據的大小(基數和寬度)以及執行的物理操作的類型。

如果您的查詢碰巧導致成本估算不准確,則優化器選擇的策略很可能不是最優的,甚至可能根本不是很好。

不准確的成本有很多原因,包括對基礎對象的不具代表性的統計資訊,以及在查詢中使用不透明或難以估計的謂詞。有了良好的統計數據、合理大小的查詢、簡單的比較操作和關係模式,估計(以及因此優化器的物理計劃選擇)至少足夠好的機會是非常好的。

簡化優化器工作的一種方法是將復雜查詢的一部分(或根本沒有得到良好估計的查詢)具體化到臨時表中。這些為優化器提供了直接的基數資訊,SQL Server 通常可以自動創建臨時表的統計資訊以提供進一步的有用資訊。最後但並非最不重要的一點是,臨時表允許您向其中添加特定的索引,這是值得的。

如果使用*得當**,臨時表是向優化器提供資訊的好方法,即使底層數據的分佈和大小發生變化,也能生成可靠的執行計劃。

如果您已經完成了統計、索引和查詢的書面形式,那麼在這裡使用臨時表可能是最佳選擇。根據問題中提供的資訊,並且不知道作者的專業水平,不可能肯定地說。

  • 合理使用意味著例如限制所需臨時表的數量、大小和寬度,以及使用頻率。SELECT * INTO #temp FROM dbo.MyHugeTable;例如,這是不明智的。

引用自:https://dba.stackexchange.com/questions/131022