當使用連結伺服器(Linked Servers)時,最昂貴的代價就是網絡帶寬間大量資料的傳輸。在正确的伺服器書寫正确的代碼是非常重要的,因為每一個錯誤都會導緻在網絡帶寬上付出非常昂貴的代價。 下面是使用連結伺服器(Linked Servers)時的幾個常見錯誤:
1:使用推送方式而不是拉方式取數
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分鐘
<code>我像這樣修改了查詢語句</code>
<code></code>
<code><code> </code></code>
<code>這樣重寫SQL後,查詢語句隻跑了一秒就查詢出結果了,保持SQL腳本簡單。</code>
<code>5:當資料庫位于同一個執行個體時使用連結伺服器(Linked Server) </code>
<code>這種場景的性能損耗可能不像其它場景那樣明顯,但是這種方式比使用資料庫字首(Database.dbo.TableName)要慢</code>
<code>如果你想差別這兩種情形,可以在測試資料庫測試、對比這兩種方法的性能,然後決定性能的提升是否值得在生産環境修改代碼。在某些情況下,它是會提升性能的。</code>
<code> </code>
<code>---------------------------------------自己的體會、了解----------------------------------------------</code>
<code> 關于SQL SERVER的連結伺服器(Linked Servers)這項功能,跨資料庫/跨伺服器查詢時非常有用(比如分布式資料庫系統中),開發人員尤其喜歡使用它連接配接到遠端資料源查詢資料,甚至都到了濫用的地步。正所謂很多東西都具有兩面性,連結伺服器(Linked Servers)給跨伺服器查詢、分布式查詢帶來友善、簡單化的同時,也帶來了性能、安全等一系列問題。</code>
<code>1:性能問題</code>
<code> 在複雜環境下(大資料時代更是如此),可能需要在多個不同伺服器之間的資料庫進行資料互動。由于資料可以無處不在,開發人員自然要編寫一個查詢聯接盡可能多的資料可以不考慮它是本地的還是遠端的。于是連結伺服器的大量使用應運而生,但是連結伺服器的濫用和不合理使用可能會導緻資料庫出現很多ASYNC_NETWORK_IO等待事件。另外,書寫不好的SQL有可能導緻嚴重的性能問題。</code>
<code> 解決方法:你可以通過釋出-訂閱或者作業将資料集(表)資料先同步到本地伺服器,然後将SQL腳本中的連結伺服器去掉,這樣對SQL查詢性能有非常大的提升,尤其是查詢比較頻繁或資料量大的SQL語句。但是這樣随之而來了其它問題: 同步資料的及時性(作業同步資料)、額外的精力去管理、監控資料同步(釋出-訂閱)。</code>
<code> SQL裡面使用了Linked Servers導緻性能低下,一方面是由于網絡資料傳送的延時,另外一方面則是優化器不能很好的生成最佳的執行計劃. 解釋:由于權限問題,使用了連結伺服器(Linked Servers)的SQL導緻SQL SERVER優化器不能利用遠端伺服器這些表的統計資訊,進而不能生成最優的執行計劃。如果SQL SERVER優化器可以利用到遠端伺服器相關表的統計資訊,則連結伺服器使用的賬号必須擁有sysadmin、 db_owner, db_ddladmin這樣的角色,但是很多時候處于安全考慮,建立連結伺服器時使用的賬号往往沒有這麼大的權限。在SQL SERVER 2012 SP1中這個問題已經解決了,隻需要擁有SELECT權限就可以使用遠端伺服器相關表的統計資訊。</code>
<code>----------------------------------------------------------------------------------------------------------------</code>
<code>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:</code>
<code></code><code>sysadmin db_owner db_ddladmin</code>
<code>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.</code>
<code>---------------------------------------------------------------------------------------------------</code>
<code>2:安全問題</code>
<code> 濫用連結伺服器會導緻一個資料庫執行個體跟N個資料庫執行個體之間建立Linked Server,導緻資料庫管理、監控的變得越來越複雜,管理問題是一個,另外一個則是資料庫的安全問題。這個最是頭痛。</code>
<code>參考資料:</code>
<code>http://thomaslarock.com/2013/05/top-3-performance-killers-for-linked-server-queries/</code>