it-swarm-eu.dev

Problémy s výkonem SQL se vzdáleným dotazem na propojeném serveru

Tato sproc

create proc dbo.Get_Accounts as
begin
  declare @current_date datetime
  set @current_date = dbo.fn_currdate()

  select [fields]
  into dbo.current_accounts
  from linkedserver.database.dbo.accounts
  where date = @current_date
end

nepřetržitě selže po 10 minutách s následující chybovou zprávou:

Server: Zpráva 7399, Úroveň 16, Stav 1, Řádek 1 OLE Poskytovatel DB 'SQLOLEDB' ohlásil chybu. Provedení ukončeno poskytovatelem, protože bylo dosaženo limitu zdroje. [OLE/DB vrátil zprostředkovatel zpráva: Časový limit vypršel] OLE Sledování chyby DB [Poskytovatel OLE/DB 'SQLOLEDB' ICommandText :: Execute vrácen 0x80040e31: Provedení ukončeno poskytovatelem, protože bylo dosaženo limitu zdroje.].

Když však spustím stejný dotaz ze stejné databáze (nikoli na vzdálené) v okně interaktivního dotazu s pevně zakódovaným datem:

  select [fields]
  into dbo.current_accounts
  from linkedserver.database.dbo.accounts
  where date = '1/20/2012'

Vrací se za 30 sekund.

Lokální server je SQLSERVER 2008, vzdálený je SQLSERVER 2000.

Následující kroky jsme provedli bez úspěchu:

  • Znovu vytvořený uložený proces.
  • sp_recompile na uložené proc
  • aktualizace statistik dbo.accounts
  • upustil a znovu vytvořil indexy na dbo.accounts
  • upustil index na dbo.accounts a zkuste
  • DBCC FREEPROCCACHE & DBCC DROPCLEANBUFFERS na lokálních i vzdálených serverech
  • Restartoval vzdálený server (není snadný na lokálním serveru)

Otázky

  • Může někdo vysvětlit toto bizarní chování?
  • Nějaké návrhy na jiné možnosti, jak je opravit?
8
Bob Probst

Můžete zapnout příznak trasování 73 což možná vám poskytne podrobnější chybovou zprávu

Kolik řádků vrací reprezentativní dotaz? Jak rychlé a spolehlivé je síťové připojení mezi dvěma servery?

Je možné, že přenos velkého datového souboru trvá příliš dlouho (nad skutečným časem dotazu). Můžete zvýšit hodnotu časového limitu.

Můžete zkusit překonfigurovat nastavení časového limitu následujícím způsobem:

Nastavit časový limit vzdáleného přihlášení na 300 sekund:

sp_configure 'remote login timeout', 300
go 
reconfigure with override 
go 

Nastavit časový limit vzdáleného dotazu na 0 (nekonečné čekání):

sp_configure 'remote query timeout', 0 
go 
reconfigure with override 
go 

Aktualizace : SQL Server 2012 SP1 a dále : uživatelé s SELECT oprávnění bude mít přístup k DBCC SHOW_STATISTICS, které zlepší výkon pouze pro čtení na propojených serverech. Odkaz: https://msdn.Microsoft.com/en-us/library/ms174384 (v = sql.110) .aspx

Aktualizace : Máte pravdu v tom, že to není velikost dat nebo rychlost připojení. Zazvonil v mé mlhavé paměti zvonek a vzpomněl jsem si, kde jsem to viděl: Pomalu v aplikaci, rychle v SSMS? (Problém s propojenými servery). Není to šňupání parametrů, jsou to právě statistiky, které chybí (kvůli oprávnění), což způsobuje použití špatného plánu dotazů:

Vidíte, že se odhady liší. Když jsem běžel jako sysadmin, odhad byl 1 řádek, což je správné číslo, protože v Northwindu neexistují žádné objednávky, kde ID objednávky přesahuje 20 000. Když jsem však běžel jako obyčejný uživatel, odhad byl 249 řádků. Toto konkrétní číslo rozpoznáváme jako 30% z 830 objednávek, nebo jako odhad nerovnosti, když optimalizátor nemá žádné informace. Dříve to bylo způsobeno neznámou hodnotou proměnné, ale v tomto případě neexistuje žádná proměnná, která by mohla být neznámá. Ne, chybí to samotné statistiky.

Dokud dotaz přistupuje pouze k tabulkám na lokálním serveru, může optimalizátor vždy přistupovat ke statistikám všech tabulek v dotazu; neexistují žádné další kontroly oprávnění. To se však liší u tabulek na propojeném serveru. Když SQL Server přistupuje k propojenému serveru, neexistuje žádný tajný protokol, který se používá pouze pro komunikaci mezi servery. Ne, místo toho SQL Server používá standardní OLE DB rozhraní pro propojené servery, ať už jsou to jiné instance SQL Serveru, Oracle, textové soubory nebo váš domácí zdroj dat) a připojuje se stejně jako každý jiný uživatel. Přesné získání statistik závisí na zdroji dat a příslušném poskytovateli OLE DB). V tomto případě je poskytovatelem nativního klienta SQL Server, který načítá statistiky ve dvou krocích. to spuštěním Profiler proti vzdálenému serveru) Nejprve poskytovatel spustí proceduru sp_table_statistics2_rowset, která vrací informace o tom, které sloupcové statistiky jsou, stejně jako jejich kardinálnost a informace o jejich hustotě. Ve druhém kroku poskytovatel spustí DBCC SHOW_STATISTICS, příkaz , který vrací úplnou distribuční statistiku. (Tento příkaz se podíváme blíže v tomto článku.) Zde je přehled: Chcete-li spustit DBCC SHOW_STATISTICS, musíte být členem sysadmin role serveru nebo libovolné z databázových rolí db_owner nebo db_ddladm. v.

A proto jsem dostal odlišné výsledky. Když jsem běžel jako sysadmin, dostal jsem kompletní statistiku distribuce, která naznačovala, že neexistují žádné řádky s ID objednávky> 20000 a odhad byl jeden řádek. (Připomeňme, že optimalizátor nikdy nepředpokládá nulové řádky ze statistik.) Ale při spuštění jako obyčejný uživatel selhal DBCC SHOW_STATISTICS s chybou oprávnění. Tato chyba nebyla propagována, ale místo toho optimalizátor připustil, že neexistují žádné statistiky a používá výchozí předpoklady. Protože získával informace o mohutnosti, zjistil, že vzdálená tabulka má 830 řádků, z čehož vyplývá odhad 249 řádků.

Kdykoli narazíte na problém s výkonem, kde je dotaz, který zahrnuje přístup k propojenému serveru, v aplikaci pomalý, ale při testování ze SSMS se spustí rychle, měli byste vždy zjistit, zda by příčinou mohla být nedostatečná oprávnění ve vzdálené databázi. (Nezapomeňte, že přístup k propojenému serveru nemusí být v dotazu zjevný, ale mohl by být v pohledu skrytý.) Pokud zjistíte, že problém ve vzdálené databázi je problém, jaké akce byste mohli provést?

  • Můžete přidat uživatele do role db_ddladmin, ale protože jim to dává právo přidávat a rušit tabulky, není to vhodné.

  • Ve výchozím nastavení, když se uživatelé připojí ke vzdálenému serveru, připojí se jako oni, ale můžete nastavit přihlašovací mapování pomocí sp_addlinkedsrvlogin, takže uživatelé budou mapovat proxy účet, který má členství v db_ddladmin. Upozorňujeme, že tento účet proxy musí být přihlášení SQL, takže toto není možnost, pokud vzdálený server nemá povoleno ověřování SQL. Také toto řešení je z bezpečnostního hlediska poněkud pochybné, i když je to lepší předchozí návrh.

  • V některých případech můžete přepsat dotaz pomocí OPENQUERY a vynutit vyhodnocení na vzdáleném serveru. To může být zvláště užitečné, pokud dotaz obsahuje několik vzdálených tabulek. (Může však také selhat, protože optimalizátor nyní získává ze vzdáleného serveru ještě méně statistických informací.)

  • Můžete samozřejmě použít plnou baterii rad a plánových průvodců, abyste získali plán, který chcete.

  • Nakonec byste se měli zeptat sami sebe, zda je tento přístup na propojený server potřebný. Možná by mohly být databáze na stejném serveru? Mohla by se data replikovat? Nějaké jiné řešení?

11
Mitch Wheat

Co se stane, když to zkusíte (tj. Výslovně označíte, co by se mělo na vzdáleném serveru spustit) ?:

select [fields]
into dbo.current_accounts
from OPENQUERY(linkedserver, 'SELECT [fields] FROM database.dbo.accounts where date = ''1/20/2012''');

Mám podezření, že ve vašem případě nad SQL Server jen tahá celou tabulku ze vzdáleného serveru a pak lokálně spouští dotaz (viděl jsem, že se to stalo mnohokrát v minulosti). Dávám přednost tomu, aby byl explicitní (buď pomocí OPENQUERY nebo vytvořením SP na vzdáleném serveru), takže není žádná šance na záměnu.

2
Gareth

Protože se jedná o problém ressource, může být paměťová oblast mimo server SQL použitá k načtení externích ovladačů a CLR možná blízko jeho limitu. Výchozí hodnota je 256 MB. Chcete-li tento problém obejít, navrhuji, abyste se obrátili na správce konfigurace serveru SQL, kartu Upřesnit a na konec spouštěcích parametrů přidali volbu -g; -g1024 a restartovali službu SQL Server. Obvykle to dělám, protože používáme vysoký počet propojených serverů. http://msdn.Microsoft.com/en-us/library/ms190737.aspx

1
nopol

Mám dva nápady, které by mohly pomoci. Také vám řeknu, že jsem smíchal smůlu s výkonnými dotazy na propojené servery. Takže moje první doporučení je vyhnout se, pokud můžete.

Mým prvním nápadem je nainstalovat uloženou proceduru do pole SQL Server 2000, mít odkaz na místní server. Uloženou proceduru pak můžete provést na dálku.

exec linkedserver.database.dbo.Get_Accounts

Pokud se můžete vydat touto cestou, mělo by to ohromně zlepšit výkon.

Moje druhá myšlenka je dostat se k plánu odhadovaných dotazů při spuštění uložené procedury. Ukazuje vám, co zabírá tolik času? Jedním z možných problémů je to, že účet, který používáte na propojeném serveru, nemusí mít dostatečné oprávnění k získání statistik tabulky (pro propojený server potřebujete více oprávnění než pro místní server). A to může způsobit, že dotazy budou neuvěřitelně pomalé. Můžete si přečíst více o tomto konkrétním problému zde .

1
Jeff Siver