2010-11-03 143 views
22

使用SqlServer Views有什麼缺點?使用SqlServer視圖有什麼缺點?

我經常創建視圖以非規範化的形式顯示我的數據。

我發現它更容易,因此更快,更容易出錯,更多的自我記錄,查詢這些連接之一,而不是生成複雜的查詢與許多表之間的複雜連接。特別是當我從不同角度分析相同的數據(許多相同的字段,同一表連接)時。

但是,創建和使用這些視圖是否有成本?

我是放慢(或加速?)查詢處理?

+1

+1根據我的經驗有無知和誤傳分貝的意見數量驚人的。可能會有很多關於哪些視圖做什麼以及如何做的討論,但是我不確定它們是否被這樣構建,以及答案是否明顯。 – 2010-11-03 14:00:06

+18

@Mr Shoubs - 我認爲人們在這裏提出問題,即使答案很容易被搜索到,因爲他們希望提供的交互性和後續/問答,我不認爲我們應該勸阻。 – JNK 2010-11-03 14:00:12

+0

@保羅 - 打我吧! – JNK 2010-11-03 14:00:36

回答

18

當談到視圖有優點和缺點。

優點:

  1. 它們是虛擬表,而不是存儲在數據庫中作爲不同的對象。所有存儲的都是SELECT語句。
  2. 它可以作爲一種安全措施,通過限制用戶可以看到的內容。
  3. 它可以通過將常用複雜查詢封裝到視圖中來使其更容易閱讀。儘管如此,這是一把雙刃劍 - 見缺點#3。

缺點:

  1. 它沒有高速緩存,所以它不會是一樣快的存儲過程優化的執行計劃。
  2. 由於它基本上只是一個SELECT的抽象,所以比純粹的SELECT稍微慢一些。
  3. 它可以隱藏複雜性並導致陷入困境。 (請注意:ORDER BY not honored)。

我個人的觀點是不使用視圖,而是使用存儲過程,因爲它們提供視圖的安全性和封裝性,而且還具有改進的性能。

+4

我認爲最大的危險來自劣勢#3。隱藏的複雜性是潛在的危險。通常情況下,使用視圖的目的是「簡化」,但從長遠來看最終會產生更多問題。 – GrowlingDog 2010-11-03 15:27:09

+2

你能否解釋ORDER BY not Honored Gotcha以及它如何體現自己。如果你想回答,我有一個問題。 http://stackoverflow.com/questions/5901558/is-order-by-honoured-in-sql-server-views – 2011-05-05 17:23:57

7

視圖的效率很大程度上取決於底層表。該視圖實際上只是一種有組織的一致方式來查看查詢結果。如果用於形成視圖的查詢很好,並且在基礎表上使用適當的索引,則視圖不應該對性能產生負面影響。

在SQL Server中,您也可以使用create materialized or indexed views(因爲SQL Server 2000),這會提高速度。

+1

一如既往,未歸因和未註釋的downvotes表示讚賞:P – JNK 2010-11-03 15:35:23

4

我也經常使用視圖。但是需要注意的是,如果您的基礎表經常變化(尤其是在開發過程中),那麼使用大量視圖可能難以維護。

編輯:話雖如此,我發現能夠簡化和重複使用複雜查詢的便利和優勢勝過維護問題,尤其是在負責任地使用視圖的情況下。

1

當我開始時,儘管視圖增加了性能開銷,但是體驗描繪了一個不同的故事(視圖機制本身的開銷可以忽略不計)。

這一切都取決於底層查詢是什麼。退房索引視圖herehere,最終你應該測試性能兩種方式獲得清晰的性能配置

+0

Dude ...放棄態度和證明y我們的貼子.... – 2010-11-03 14:04:46

+0

好的,好吧,談論被跳 - 我聽起來很糟糕,然後打算 – 2010-11-03 14:06:23

+0

@Mr Shoubs。也許很多信息,但也可能是太多的信息。我不想花費3天時間閱讀數百頁文檔。我只想要一個簡單的答案。我想我可以要求一個好的鏈接,讓我回答這個問題。然後依靠那些得票最多的人。 – 2010-11-03 16:53:09

3

一個缺點的看法,我已經在性能上把它們納入到分佈式查詢時遇到的一個潛水。這篇文章討論了 - 雖然我在演示中使用了高度人造的數據,但我在「現實世界」中一次又一次地遇到了這個問題。

尊重你的意見,他們會很好的對待你。

10

使用視圖的一個可能的不利之處是你抽象了底層設計的複雜性,這可能導致初級開發人員和報表創建者的濫用。

對於一個特別大且複雜的項目,我設計了一組視圖,這些視圖主要由報告設計人員用來填充水晶報表。幾周後,我發現初級開發者已經開始使用這些視圖來獲取聚集並加入這些已經很大的視圖,因爲他們在那裏並且很容易被使用。 (數據庫中有一個強大的EAV設計元素。)在初級開發人員開始詢問爲什麼看似簡單的報告需要花費很多分鐘才能執行之後,我發現了這一點。

4

當視圖包含邏輯,列,行或表最終未被最終查詢使用的表時,視圖可能會損害性能。我不能告訴你有多少次我看到的東西,如:

SELECT ... 
FROM (View with complex UNION of ActiveCustomer and InactiveCustomer tables) 
WHERE Active = True 

(從而篩選出包括在從InactiveCustomer表中的觀點,即所有行),或

SELECT (one column) 
FROM (view that returns 50 columns) 

( SQL必須檢索大量數據,然後在後面的步驟丟棄的,其可能與其他列是昂貴的檢索,想通過書籤查找),或

SELECT ... 
FROM (view with complex filters) 
WHERE (entirely different filters) 

(它可能是SQL可以有使用,如果表被直接查詢更適當的指數), 或

SELECT (only fields from a single table) 
FROM (view that contains crazy complex joins) 

(大量的CPU開銷通過加入,和不必要的IO爲表讀取稍後丟棄),或我喜歡的:

SELECT ... 
FROM (Crazy UNION of 12 tables each containing a month of data) 
WHERE OrderDate = @OrderDate 

(僅當真正需要讀取1時纔讀取12個表格)。

大多數的情況下,SQL足夠聰明,可以「查看封面」並提出有效的查詢計劃。但在其他情況下(特別是非常複雜的情況下),它不能。在上述每種情況下,答案都是刪除視圖並查詢基礎表。

最起碼(即使你認爲SQL將足夠聰明反正去優化它),消除了看法有時會令自己的查詢調試和優化更容易(更明顯一點需要做什麼) 。

+0

不知道是什麼問題:SELECT ... 從(查看與瘋狂聯合主動和無效客戶) WHERE Active = True。你是否應該說還有兩個視圖,一個是所有活躍客戶,另一個是非活動客戶。所以如果你只需要激活你查詢'活躍'視圖等? – 2010-11-03 16:47:03

+0

@Lill好吧,在這個(做作)的例子中,視圖組合了來自表格的數據,然後由最終查詢過濾出來。所以直接查詢ActiveCustomer表,並完全繞過視圖。 – BradC 2010-11-03 17:05:52

+0

編輯過的帖子,使這個例子更清晰。 – BradC 2010-11-03 17:23:35

0

我最大的'抱怨'是,ORDER BY不能在視圖中工作。雖然這是有道理的,但如果沒有預料到的話,它可能會跳起來咬人。因此,我必須將切換到使用視圖到SPROCS(它們有足夠多的問題),在某些情況下,我無法在以後指定ORDER BY。 (我希望有一個帶有「最終視圖」的構造 - 例如可能包括按語義排序)。

http://blog.sqlauthority.com/2010/10/03/sql-server-the-limitations-of-the-views-eleven-and-more/(限制#1是關於ORDER BY :-)

2

什麼是SQL Server中的視圖的各種限制?

觀前11侷限性

  • 視圖不支持COUNT();但是,它可以支持COUNT_BIG(
  • ORDER BY子句中查看不起作用
  • 定期查詢或存儲過程給我們的靈活性,當我們需要另一列;我們可以立即爲常規查詢添加一列。如果我們想要對視圖執行相同的操作,那麼我們必須先修改它們
  • 視圖上創建的索引不常用
  • 一旦創建了視圖並且基本表中添加或刪除了任何列,通常不反映在視圖,直到它被刷新
  • UNION操作無法在索引視圖允許
  • 我們不能創建一個嵌套的查看情況的指數意味着我們不能從另一視圖建立了一個視圖中創建索引。
  • 自連接不能在索引視圖允許
  • 外索引視圖加入不允許
  • 跨數據庫查詢在索引視圖中不允許

來源SQL MVP皮納爾戴夫

http://blog.sqlauthority.com/2010/10/03/sql-server-the-limitations-of-the-views-eleven-and-more/

-2

以下是允許在視圖中引用命令的SQL hack:

create view toto1 as 
select top 99.9999 percent F1 
from Db1.dbo.T1 as a 
order by 1 

但我的偏好是使用Row_Number

create view toto2 as 
select *, ROW_NUMBER() over (order by [F1]) as RowN from ( 
select f1 
from Db1.dbo.T1) as a