SQL SERVER - 連結伺服器和查詢性能
我遇到了與 SQL Server/連結伺服器/視圖相關的性能問題。我希望你能幫助我理解做我想做的最好的方法是什麼=)。
- 我有一個數據庫 K,它有 3 個連結伺服器 L1、L2、L3 到 3 個數據庫 X、Y、Z。
- 在 X、Y、Z 中,我分別有 3 個視圖,稱為 V1、V2、V3。
- 我想通過數據庫 K 與連結伺服器 L1、L2、L3 查詢 V1、V2、V3 的聯合。
經過一番測試,情況是這樣的:
- 在 SSMS 中,如果我執行這個偽查詢
SELECT * FROM (L1.V1 u L2.V2 u L3.V3) WHERE some filters
,性能真的很棒- 如果我在數據庫 K 中創建一個視圖 VK,其中包含三個視圖的聯合,然後我執行查詢
SELECT * FROM VK WHERE some filters
,則性能比案例 1 差問題
- 為什麼表現如此不同?
- 在案例 2 中如何提高性能?
我對提高案例 2 的性能很感興趣,因為我需要一個視圖來在我們的軟體中使用 nHbinernate 進行映射……
提前致謝,問候
約翰·艾倫發布後的更新
好的,我嘗試但沒有結果。我不是 DBA,我在 DB 配置方面的技能非常有限。我們可以一步一步來嗎?
- 在遠端伺服器 ( ) 上,我通過 security->logins->new login
called Y
創建了一個新帳戶 ( )。called linkedserver
我選擇登錄名,然後選擇 sql 身份驗證,然後選擇密碼。對於預設數據庫,我選擇master
. 在server roles
選項卡中,我選擇public
. 在User mapping
選項卡中,我選擇遠端查詢中涉及的數據庫,並為每個數據庫選擇db_ddladmin
和public
角色。然後,對於遠端查詢涉及的每個數據庫,我檢查了linkedserver使用者的有效權限,有很多ALTER
很多的CREATE
權限,但沒有SHOW PLAN(然後我也選擇了這個)。called X
在Y 的連結伺服器所在的數據庫伺服器 ( ) 上,我創建了一個連結伺服器 (called L1
)。在安全選項卡中,我選擇local user sa
並remote user linkedserver
使用其密碼。當我在沒有 VIEW 的情況下跨 L1 執行查詢時,我得到了很好的結果,如果我將查詢置於 VIEW 低性能中,則沒有任何改變……
我想我做錯了一步,但我不知道在哪裡……
為了更好的清晰度
這是我使用連結伺服器在沒有視圖的情況下執行的查詢:
select * from ( select * from dolph.agendasdn.dbo.vistaaccettazionegrp union select * from dolph.acampanet.dbo.vistaaccettazionegrp union select * from municipio.dbnet.dbo.vistaaccettazionegrp ) a where cognome = 'test' and nome = 'test'
在視圖中我只放了這段程式碼
select * from dolph.agendasdn.dbo.vistaaccettazionegrp union select * from dolph.acampanet.dbo.vistaaccettazionegrp union select * from municipio.dbnet.dbo.vistaaccettazionegrp
然後我打電話
select * from VIEW where cognome = 'test' and nome = 'test'
所以..
- 第一種情況0-1秒。
- 第二種情況> 15秒…
我認為這很荒謬!
執行計劃
帶有普通查詢的執行計劃,不使用視圖:
使用視圖的執行計劃:
您的問題以統計和估計開始和結束。我已經在我的伺服器上重現了您的情況,並發現了一些有趣的提示和解決方法。
首先,讓我們看一下您的執行計劃:
當使用視圖時,我們可以看到執行遠端查詢後應用了過濾器,而沒有視圖則根本沒有應用過濾器。事實上,在通過網路檢索數據之前,過濾器是在遠端伺服器上的Remote Query中應用的。 好吧,顯然在遠端伺服器上應用過濾器,從而檢索更少的數據是一個更好的選擇,而且很明顯,只有在不使用視圖時才會發生這種情況。
那麼……有什麼有趣的……?
令人驚訝的是,當我將過濾器從更改
cognome = 'test'
為cognome = N'test'
(字元串的 unicode 表示)時,視圖使用了與第一個查詢相同的執行計劃。我猜原因是不知何故,當使用視圖 SQL Server 估計會有少量從(遠端)查詢返回的行,並且本地過濾會更便宜,但是當 SQL Server 必須隱式轉換
NVARCHAR
為時VARCHAR
,無法再使用統計資訊,也沒有做出在本地過濾的決定。我在本地查找了統計資訊,但視圖沒有統計資訊,所以我的猜測是視圖以一種臨時查詢沒有的方式使用遠端統計資訊,而不是做出錯誤的決定。
好的,那麼解決問題的方法是什麼?
我之前說過有一種解決方法(至少在有人提出更好的解決方案之前),不,我不是說對你的字元串使用 unicode。
我想先給出一個答案,我仍然需要找到原因,但是當使用
Inline Function
SQL Server 時,它的行為與查詢完全相同(沒有視圖),所以用函式替換視圖將給出相同的結果,在一個簡單的查詢,並具有良好的性能(至少在我的環境中)。我給你的程式碼建議是:
CREATE FUNCTION fn_anagrafiche2() RETURNS table AS RETURN ( SELECT * FROM dolph2.agendasdn.dbo.vistaanagraficagrp UNION SELECT * FROM dolph2.acampanet.dbo.vistaanagraficagrp UNION SELECT * FROM municipio2.dbnet.dbo.vistaanagraficagrp ) GO
查詢將是:
SELECT * FROM fn_anagrafiche2() WHERE cognome = 'prova'
這適用於我的伺服器,但當然要先測試它。
**注意:**我根本不建議使用
SELECT *
,因為它很容易在未來出現錯誤,我只是使用它,因為它在你的問題中,當我可以添加此註釋時,我不需要更改它:)