Sql-Server

SQL SERVER - 連結伺服器和查詢性能

  • August 5, 2014

我遇到了與 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 的聯合。

經過一番測試,情況是這樣的:

  1. 在 SSMS 中,如果我執行這個偽查詢SELECT * FROM (L1.V1 u L2.V2 u L3.V3) WHERE some filters,性能真的很棒
  2. 如果我在數據庫 K 中創建一個視圖 VK,其中包含三個視圖的聯合,然後我執行查詢SELECT * FROM VK WHERE some filters,則性能比案例 1 差

問題

  • 為什麼表現如此不同?
  • 在案例 2 中如何提高性能?

我對提高案例 2 的性能很感興趣,因為我需要一個視圖來在我們的軟體中使用 nHbinernate 進行映射……

提前致謝,問候

約翰·艾倫發布後的更新

好的,我嘗試但沒有結果。我不是 DBA,我在 DB 配置方面的技能非常有限。我們可以一步一步來嗎?

  1. 在遠端伺服器 ( ) 上,我通過 security->logins->new logincalled Y創建了一個新帳戶 ( )。called linkedserver我選擇登錄名,然後選擇 sql 身份驗證,然後選擇密碼。對於預設數據庫,我選擇master. 在server roles選項卡中,我選擇public. 在User mapping選項卡中,我選擇遠端查詢中涉及的數據庫,並為每個數據庫選擇db_ddladminpublic角色。然後,對於遠端查詢涉及的每個數據庫,我檢查了linkedserver使用者的有效權限,有很多ALTER很多的CREATE權限,但沒有SHOW PLAN(然後我也選擇了這個)。
  2. called X在Y 的連結伺服器所在的數據庫伺服器 ( ) 上,我創建了一個連結伺服器 ( called L1)。在安全選項卡中,我選擇local user saremote 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 FunctionSQL 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 *,因為它很容易在未來出現錯誤,我只是使用它,因為它在你的問題中,當我可以添加此註釋時,我不需要更改它:)

引用自:https://dba.stackexchange.com/questions/43754