當使用鏈接服務器(Linked Servers)時,最昂貴的代價就是網絡帶寬間大量數據的傳輸。在正確的服務器書寫正確的代碼是非常重要的,因為每一個錯誤都會導致在網絡帶寬上付出非常昂貴的代價。 下面是使用鏈接服務器(Linked Servers)時的幾個常見錯誤:
1:使用推送方式而不是拉方式取數
出人意料之外的是,使用鏈接服務器推送數據比拉取數據慢得多。Linchi Shea寫了一篇很好的博客討論這個。
Linchi Shea 使用openquery來說明兩者間的差異,但是這個也會發生在使用鏈接服務器的SQL語句中(這裡不好翻譯,其實就是查詢中使用Linked Server需要用到 LinkServer.DatabaseName.dbo.TableName)
2: 使用JOIN
跨服務器查詢時,為了在兩台服務器之間的數據集之間執行JOIN操作,SQL Server需要將數據從一台服務器傳送到另外一台服務器。如果傳送的數據是一個非常大的表,這個過程可能會非常痛苦。通常來說,數據會從遠程服務器傳送到本地服務器。為了防止大量數據在服務器之間大傳送,你可以通過在查詢條件中過濾數據,通過一個遠程存儲過程只取回相關數據來達到目的,萬一你需要使用INNER JOIN關聯兩個不同服務器之間的數據集,而且本地表的數據量遠小於遠程服務器的那個表。你可以使用REMOTE JOIN HINT, 這樣就會將數據從本地服務器將數據傳送到遠程服務器,從而提高性能
3:使用UNION
正如JOIN操作,UNIION不同服務器之間的兩個數據集必定導致從遠程服務器傳送數據到本地服務器。即使你執行遠程查詢合並(UNION)同一個遠程服務器的兩個數據集,還是會先將兩個數據集傳送到本地服務器,然後UNION兩個數據集,可以通過遠程存儲過程,函數或視圖先UNION數據庫來阻止這個
4:書寫太復雜的查詢語句
優化器不能總是能明白你需要做什麼,尤其是你的SQL語句中使用了鏈接服務器(Linked Server)時,例如, 我遇到過一個類似如下SQL語句,執行了10分鐘
1: SELECT *
2: FROM LocalTable
3: WHERE SomeColumn <
4: (SELECT COUNT(*)
5: FROM RemoteServer.SomeDB.dbo.SomeTable
6: WHERE SomeColumn > 100)
我像這樣修改了查詢語句
1: DECLARE @Count INT
2: SELECT @Count = COUNT(*)
3: FROM RemoteServer.SomeDB.dbo.SomeTable
4: WHERE SomeColumn > 100
5:
6: SELECT *
7: FROM LocalTable
8: WHERE SomeColumn < @Count
這樣重寫SQL後,查詢語句只跑了一秒就查詢出結果了,保持SQL腳本簡單。
5:當數據庫位於同一個實例時使用鏈接服務器(Linked Server)
這種場景的性能損耗可能不像其它場景那樣明顯,但是這種方式比使用數據庫前綴(Database.dbo.TableName)要慢
如果你想區別這兩種情形,可以在測試數據庫測試、對比這兩種方法的性能,然後決定性能的提升是否值得在生產環境修改代碼。在某些情況下,它是會提升性能的。
關於SQL SERVER的鏈接服務器(Linked Servers)這項功能,跨數據庫/跨服務器查詢時非常有用(比如分布式數據庫系統中),開發人員尤其喜歡使用它連接到遠程數據源查詢數據,甚至都到了濫用的地步。正所謂很多東西都具有兩面性,鏈接服務器(Linked Servers)給跨服務器查詢、分布式查詢帶來方便、簡單化的同時,也帶來了性能、安全等一系列問題。
1:性能問題
在復雜環境下(大數據時代更是如此),可能需要在多個不同服務器之間的數據庫進行數據交互。由於數據可以無處不在,開發人員自然要編寫一個查詢聯接盡可能多的數據可以不考慮它是本地的還是遠程的。於是鏈接服務器的大量使用應運而生,但是鏈接服務器的濫用和不合理使用可能會導致數據庫出現很多ASYNC_NETWORK_IO等待事件。另外,書寫不好的SQL有可能導致嚴重的性能問題。
解決方法:你可以通過發布-訂閱或者作業將數據集(表)數據先同步到本地服務器,然後將SQL腳本中的鏈接服務器去掉,這樣對SQL查詢性能有非常大的提升,尤其是查詢比較頻繁或數據量大的SQL語句。但是這樣隨之而來了其它問題: 同步數據的及時性(作業同步數據)、額外的精力去管理、監控數據同步(發布-訂閱)。
SQL裡面使用了Linked Servers導致性能低下,一方面是由於網絡數據傳送的延時,另外一方面則是優化器不能很好的生成最佳的執行計劃. 解釋:由於權限問題,使用了鏈接服務器(Linked Servers)的SQL導致SQL SERVER優化器不能利用遠程服務器這些表的統計信息,從而不能生成最優的執行計劃。如果SQL SERVER優化器可以利用到遠程服務器相關表的統計信息,則鏈接服務器使用的賬號必須擁有sysadmin、 db_owner, db_ddladmin這樣的角色,但是很多時候處於安全考慮,創建鏈接服務器時使用的賬號往往沒有這麼大的權限。在SQL SERVER 2012 SP1中這個問題已經解決了,只需要擁有SELECT權限就可以使用遠程服務器相關表的統計信息。
下面這段摘自TOP 3 PERFORMANCE KILLERS FOR LINKED SERVER QUERIES
----------------------------------------------------------------------------------------------------------------
1. INSUFFICIENT PERMISSIONS
Without a doubt this is the number one reason for why linked server query performance suffers. Historically in order for SQL Server to take advantage of using statistics on the remote server then the login used to make the connection on the remote servers needed sufficient rights. The role needed would have been one of the following:
sysadmin
db_owner
db_ddladmin
If you don’t have sufficient permissions then you aren’t able to use stats, and this is killing your performance across that linked server connections. So for everyone that has been assigning the db_datareader role to remote logins you are sacrificing performance for security. While that may be an acceptable tradeoff in your shop, I am willing to wager that most admins have no idea about this silent performance killer.
A good example of identifying these symptoms are contained in this article: http://www.sql-server-performance.com/2006/api-server-cursors/
In SQL 2012 SP1 the permissions to view the statistics on an object have been modified so that a user with SELECT permission would be able to use the stats on the remote tables. Check this link for more details in the ‘Permissions’ section towards the bottom.
2:安全問題
濫用鏈接服務器會導致一個數據庫實例跟N個數據庫實例之間建立Linked Server,導致數據庫管理、監控的變得越來越復雜,管理問題是一個,另外一個則是數據庫的安全問題。這個最是頭痛。
原文地址:http://www.dbnewsfeed.com/2012/09/08/5-performance-killers-when-working-with-linked-servers/