2013-02-11 81 views
3

我有兩個表,每個大約500k行(並且在增長)。插入/更新發生在這些不斷,有時每分鐘100。系統出現性能問題,即超時,基本插入到這些表中。我們調整了索引,並進行了通常的優化。但我想知道,如果這兩個表在5個觀點中被大量參與引用的事實可能是有害的。我一直認爲,也許錯誤地認爲,隨着基礎表的變化,引用它們的觀點也發生變化。因此,如果表格發生了很大的變化,也許我們的系統會不停地播放追趕式更新視圖而不知所措。何時更新SQL Server視圖?

+0

這兩個回答都是準確的。視圖基本上是在聯接中使用子查詢的簡寫。有多種原因可能會導致您的超時。因爲你說超時而不是死鎖我假設插入是從SQL以外被調用。你能否提供一些關於超時發生的更多信息?可能是因爲您的超時閾值設置得太低(例如,使用SqlCommand對象)。 – 2013-02-11 15:38:25

+1

我是在存儲代碼中使用視圖的一個非常大的對手。如果您可以使用視圖,那麼您也可以手動編寫聯接,而不使用視圖。一種觀點的問題在於,您試圖針對最有可能不需要整個解決方案的情況使用一站式解決方案。請記住,SQL在優化本身方面非常出色,它基於所使用的表以及每個表使用的特定列來執行此操作。如果你的視圖返回6列,但你只需要4個,那麼你的查詢由於視圖而本質上是低效的。 – 2013-02-11 15:40:01

+2

@ Love2Learn--不完全正確。如果您只從視圖中選擇4列,則優化程序可以使用該信息並生成一個無法提供其他列的計劃,如果這樣的計劃可行的話。正如我所說的,它們的優化適用於整個查詢(將視圖定義擴展到該查詢中)。 – 2013-02-11 15:46:53

回答

10

除非他們indexed views(你有沒有在你的問題提這樣)一個觀點,他們沒有「更新」在所有。

普通視圖與C中的宏相似 - 它們只是隱藏較大表達式的一部分的便捷簡寫。它們擴展到引用它們的任何語句的解析樹中,然後整個樹被編譯和優化 - 在使用點。


對於索引視圖,基本上是正確的 - 視圖作爲在基表中執行更改的同一事務的一部分進行維護。然而,索引視圖的規則的設計使得這種更新活動不應該承受太大的懲罰(它們可以在不必重新查詢整個基表的情況下被維護)。

+0

絕對不是索引視圖。我會在別處尋找問題,謝謝! – 2013-02-11 15:51:28

2

SQLServer的意見沒有被緩存,所以每次您請求的查詢被執行

4

這取決於:

1)如果視圖沒有被索引,那麼視圖中展開

-- View definition 
CREATE VIEW Sales.v_SalesOrderDetail 
AS 
SELECT h.SalesOrderID, h.SalesOrderNumber, h.OrderDate, 
     d.SalesOrderDetailID, d.OrderQty, d.UnitPrice, d.LineTotal, 
     p.ProductID, p.Name AS ProductName, p.Color AS ProductColor 
FROM Sales.SalesOrderHeader h 
INNER JOIN Sales.SalesOrderDetail d ON h.SalesOrderID = d.SalesOrderID 
INNER JOIN Production.Product p ON d.ProductID = p.ProductID 
GO 

-- View usage 
SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName 
FROM Sales.v_SalesOrderDetail v 
WHERE v.ProductColor='Red'; 
GO 

如果我們在執行計劃(SSMS:按Ctrl + M), enter image description here 然後我們將看到該視圖(FROM Sales.v_SalesOrderDetail v)被展開,服務器只查詢兩個表:Sales.SalesOrderDetail dProduction.Product p。更多的,我們可以看到Sales.SalesOrderHeader hSales.SalesOrderDetail d之間的連接被刪除,因爲:

  • SELECT條款(SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName)不包括來自Sales.SalesOrderHeader表列,

  • 這個兩分表之間有一個外鍵約束和

  • 該FK約束是可信的。

2)如果該視圖索引(這意味着有在視圖中定義的UNIQUE CLUSTERED INDEX)和SQL Server版本是企業,那麼該視圖可以擴展或不。如果版本<>企業索引視圖被擴展。我們可以強制服務器不使用NOEXPAND提示擴展的[索引]觀點:

-- View definition 
CREATE VIEW Sales.v_SalesOrderDetail2 
WITH SCHEMABINDING 
AS 
SELECT h.SalesOrderID, h.SalesOrderNumber, h.OrderDate, 
     d.SalesOrderDetailID, d.OrderQty, d.UnitPrice, d.LineTotal, 
     p.ProductID, p.Name AS ProductName, p.Color AS ProductColor 
FROM Sales.SalesOrderHeader h 
INNER JOIN Sales.SalesOrderDetail d ON h.SalesOrderID = d.SalesOrderID 
INNER JOIN Production.Product p ON d.ProductID = p.ProductID 
GO 

-- Defining the UNIQUE CLUSTERED INDEX 
CREATE UNIQUE CLUSTERED INDEX PK_v_SalesOrderDetail2 
ON Sales.v_SalesOrderDetail2 (SalesOrderDetailID); 
GO 

-- View usage 
SELECT v.SalesOrderDetailID, v.OrderQty, v.UnitPrice, v.ProductName 
FROM Sales.v_SalesOrderDetail2 v WITH (NOEXPAND) 
WHERE v.ProductColor='Red'; 
GO 

在這種情況下,我們可以看到,執行計劃 enter image description here 包括Clustered Index Scan PK_v_SalesOrderDetail2操作。因此,它使用第二個視圖中定義的索引。

請注意:SQL Server bug indexed view + MERGE

-1

調整索引是好的,但可能值得考慮多久更新一次以及何時更新這些索引的統計信息。此外,使用緩衝區表來保存插入,然後可以每5分鐘或10分鐘或以適合您的系統的批量操作插入插入,這可能會有所幫助(將其放置在單獨的物理磁盤上將是一個好主意。)這樣做會使在90%的時間內選擇的速度要快得多,而其他10%的時間沒有太多差。