SQL Server橫向擴展:設計,實現與維護(3)- 分布式分區視圖的實現
在上一篇文章中,我們已經說到分布式分區視圖采用的是Linked Server技術實現,也大致的說了下它的實現原理,我們這里對實現的內部機制點到為止,我們本系列的目的在於實戰和分析各種技術方案的使用場景。
一般而言,我們常常會使用SQL Profiler來對Linked Server進行故障排除和性能優化。在SQL Server 2005以及之后版本中,增強了查看Linked Server工作情況的事件。通過Profiler,我們可以看到OLE DB調用其他數據庫服務器的信息。
查詢的執行過程
其實,分布式分區視圖就是將一個查詢中的生成的查詢樹的一部分傳遞到遠程的數據庫中。這個道理大家應該很容易想到。在SQL Server 2000中,一個查詢的啟動命令和查詢的獲取數據行命令不能並行的進行。在SQL Server 2005以及以后,命令的啟動可以並行的執行,而且遠程數據庫的連接池和重疊使用的I/O是經過優化了的。但是,依然不能並行的執行命令去獲取數據。
大家可能不是太明白這里的講述,我下面就舉個簡單的例子說明下:
假設現在有一個使用了Linked Server的查詢,那么生成的查詢樹(注意,這里是查詢樹,是邏輯的語法樹,還不是執行計划)我們假設如下:
大家看到圖中標注紅色的部分,代表了這里的查詢樹需要最終去遠程數據庫上面執行。
當查詢樹生成好了之后,就需要去執行,此時,這個查詢樹就要被分拆到不同的遠程數據庫上面去,此時在2005中,假設上面的查詢樹需要連接4個不同的遠程數據庫,那么此時,那么,此時,就可以並行的啟動四個查詢的命令,然后這些命令將各自的查詢樹結構傳遞過去。然后這些查詢樹就會交給遠程的數據庫查詢引擎去優化,然后執行,之后遠程的數據庫就會把數據傳送回來,但是此時這個4個遠程數據庫不能同時傳送數據,只能一個個的來。
而且,在這個過程中SQL Server OLE DB會把“獲取的數據行的統計信息”發送到遠程的SQL Server中,去幫助遠程的數據庫的查詢處理器更好的工作,從而使得,從遠程情況下,允許有統計查詢處理器執行相同的查詢與本地查詢的成本估算和優化,並選擇最有效的整體查詢計划。
實現分布式分區視圖
要實現分布式分區視圖,我們就需要使用Linked Server,為了建立Linked Server,我們可以使用很多的方式:直接使用圖形化的SSMS界面,然后中對象瀏覽器中創建;使用sp_addlinkedserver這個存儲過程。
在SSMS中,我們可以很容易的申明要連接的數據庫實例的名字,而且還需要將Server Type設置為SQL Server。使用SSMS建立Linked Server的時候,很多的配置都是采用默認值,但是當使用sp_addlinkedserver的時候,我們需要配置相關的參數,特別是要設置svrproduct,這個參數的值必須是SQL Server。
下面就看個例子,使用存儲過程建立的,代碼如下:
USE MASTER
GO
EXECUTE sp_addlinkedserver ' ServerB ', N ' SQL Server '
GO
-- on instance B
USE MASTER
GO
EXECUTE sp_addlinkedserver ' ServerA ', N ' SQL Server '
GO
然后,我們需要在每個數據庫中都去建立相同的數據表,因為我們現在演示的例子是把一個表中的數據拆分放在不同的服務器上面(當然,我們還可以把原本在一個數據庫的表放在不同的數據庫中)。當我們把一個表拆分放在不同的數據庫時,需要制定一個拆分的條件,這一點和我們在SQL Server 2005的分區表中使用分區方案類似,但是這里的分區是分布式的,例如,對於Customer表,我們把CustomerID作為拆分的列,如下:
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers1to4 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 1 AND 49999),
-- other columns…
)
-- on instance B
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers5to9 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 50000 AND 99999),
-- other columns…
)
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers1to4 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 1 AND 49999),
-- other columns…
)
-- on instance B
USE SalesDB
GO
CREATE TABLE SalesSchema.Customers5to9 (
-- partitioning column
CustomerId INTEGER PRIMARY KEY
CHECK (CustomerID BETWEEN 50000 AND 99999),
-- other columns…
)
上面的代碼應該很好理解:把CustomerID從1到49999的用戶放在數據庫實例A中,50000-99999的用戶放在B中。
數據分布好了之后,我們就需要去建立視圖,從而向應用程序那邊隱藏內部的實現,代碼如下:
USE SalesDB
GO
CREATE VIEW AllCustomers AS
SELECT * FROM SalesDB.SalesSchema.Customers1to4
UNION ALL
SELECT * FROM ServerB.SalesDB.SalesSchema.Customers5to9
)
-- on instance B
USE SalesDB
GO
CREATE VIEW AllCustomers AS
SELECT * FROM ServerA.SalesDB.SalesSchema.Customers1to4
UNION ALL
SELECT * FROM SalesDB.SalesSchema.Customers5to9
)


