Vyčištění Dočasné SSRS Reports




Naše aplikace využívá SQL Server Reporting Services a umožňuje uživatelům přidávat vlastní filtry zpráv. Děláme to úpravou RDL a pak nahrát upravený RDL na serveru vytvořit novou sestavu. Problém je v tom, že poté, co zpráva spustit jednou, to už není potřeba; je to opravdu jen dočasný zpráva. Je zřejmé, že by to v konečném důsledku hodně dočasných zpráv, kterým se kolem sebe. Potřebujeme způsob, jak vyčistit těchto nahoru.


Už jsme uvažovali o externí metody, jako je vytvoření služby nebo zaměstnání pravidelně mazat zprávy, a to je pravděpodobně to, co budeme nakonec dělá když nemůžeme přijít s něčím lepším. Co jsme zvědaví zní, zda to SSRS sám poskytuje lepší způsob, jak to udělat? Mysleli jsme, že o snaze nějak použít mezipaměti instance, která by byla nastavena na vyprší, ale zdá se, funguje pouze na provedené instanci zprávy nikoliv samotné zprávě. Co se týče můžu říct, že to není způsob, jak nastavit zprávu platnosti. Existuje nějaký jiný způsob, jak dostat SSRS uklidit pro nás?


Ihned mazání sestavy není možné, protože naše poprava je asynchronní.
Vestavěný, nic. Ale psát něco sám je snadné.


Zkuste má proces, který dotazuje svůj katalog zpráv pro ty, které jsou starší než půl hodiny (nebo tak nějak). Dalo by se dokonce připojit k ReportServerTempDB aby zjistili, zda mají stále aktivní relace (v takovém případě je budete ignorovat trochu déle).


Poté, co jste je našli, je to snadné chytit, které pomocí rozhraní webových služeb a jejich odstranění z katalogu.


Ale ... Já bych vlastně se podívat na lepší způsob, jak poskytnout vlastní filtr, pomocí kódu. Jistě byste mohli poskytnout filtr jako parametr, a použít kód VB v rámci zprávy převést to, co uživatel zadá do něčeho, který by mohl být vyhodnocen pro každý řádek.


Okrást
Často toto je provedeno pomocí [„Data Driven odběry“](https://msdn.microsoft.com/en-us/library/ms169673.aspx) , ale tato funkce je k dispozici pouze v některých SQL vydáních: Enterprise a Business Intelligence, ale ne v normě.


Takže existuje celá řada kreativních řešení. Ale nemám rád žádné z nich, a všechny vyžadují spravedlivý trochu práce mimo SSRS.


Mezi řešení, které jsem viděl, patří: Vytvoření odběr a potom zakázání nebo povolení SQL úlohu, kterou odešle předplatné (identifikovatelné podle GUID).


Vytvořte si .NET obálky exe zvládnout odeslání e-mailu. Je možné spustit dotaz nejprve zjistit, kolik se vrací řádky, a pak v případě potřeby generovat zprávu a zahrnout do e-mailu. <p>i když plně souhlasím s tím, že ovládání zdroje je tím správným způsobem, chápu také, že ne všechna prostředí jsou dostatečně disciplinovaná, aby se na to mohla spoléhat sama (pokud vůbec), a že někdy je třeba provést změny přímo, aby aplikace zůstala běh, uložte klienta, co máte.</p><p>spouštěč ddl můžete použít k uchování všech revizí v tabulce v samostatné databázi (a samozřejmě tuto databázi samozřejmě často zálohovat). předpokládejme, že máte databázi nástrojů:</p><pre><code>use utility; go create table dbo.procedurechanges ( eventdate datetime not null default current\_timestamp, eventtype nvarchar(100), eventddl nvarchar(max), databasename nvarchar(255), schemaname nvarchar(255), objectname nvarchar(255), hostname nvarchar(255), ipaddress varchar(32), programname nvarchar(255), loginname nvarchar(255) ); </code></pre><p>nyní ve vaší databázi nejprve pojďme chytit to, čemu říkáme „počáteční kontrola“ - aktuální verze uložených procedur:</p><pre><code>use yourdb; go insert utility.dbo.procedurechanges ( eventtype, eventddl, databasename, schemaname, objectname ) select n'initial control', object\_definition([object\_id]), db\_name(), object\_schema\_name([object\_id]), object\_name([object\_id]) from sys.procedures; </code></pre><p>nyní, abyste zachytili následné změny, přidejte do databáze spouštěč ddl:</p><pre><code>use yourdb; go create trigger capturestoredprocedurechanges on database for create\_procedure, alter\_procedure, drop\_procedure as begin set nocount on; declare @eventdata xml = eventdata(), @ip varchar(32); select @ip = client\_net\_address from sys.dm\_exec\_connections where session\_id = @@spid; insert utility.dbo.procedurechanges ( eventtype, eventddl, schemaname, objectname, databasename, hostname, ipaddress, programname, loginname ) select @eventdata.value('(/event\_instance/eventtype)[1]', 'nvarchar(100)'), @eventdata.value('(/event\_instance/tsqlcommand)[1]', 'nvarchar(max)'), @eventdata.value('(/event\_instance/schemaname)[1]', 'nvarchar(255)'), @eventdata.value('(/event\_instance/objectname)[1]', 'nvarchar(255)'), db\_name(), host\_name(), @ip, program\_name(), suser\_sname(); end go </code></pre><p>postupem času bude snadné vidět a porovnat změny v postupech, sledovat, jak se do systému přidávají nové postupy, vidět, jak vypadají procedury, a mít dobrou představu o tom, s kým o jakékoli z těchto událostí hovořit.</p><p>více informací zde:</p><p> <a href="http://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/">http://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/</a> </p> <p>musíte použít tuto kombinaci kláves:</p><blockquote> <p><kbd>ctrl</kbd> + <kbd>shift</kbd> + <kbd>r</kbd></p> </blockquote><p>případně použijte položku nabídky:</p><blockquote> <p>úpravy&gt; intellisense&gt; aktualizovat místní mezipaměť</p> </blockquote><p>tento článek může být také užitečný (pro budoucí čtenáře, kteří mají komplikovanější problémy s intellisense):</p><ul> <li> <a href="http://www.mssqltips.com/sqlservertip/2591/troubleshooting-intellisense-in-sql-server-management-studio-2012/">odstraňování problémů s intellisense v sql server management studio</a> </li> </ul> <p><strong> <a href="http://codex.wordpress.org/faq\_troubleshooting#how\_to\_clear\_the\_.22briefly\_unavailable\_for\_scheduled\_maintenance.22\_message\_after\_doing\_automatic\_upgrade.3f">jak odstranit zprávu "krátce nedostupné pro naplánovanou údržbu" po provedení automatické aktualizace?</a> </strong></p><blockquote> <p>jako součást automatické aktualizace wordpress umístí soubor s názvem <code>.maintenance</code> do složky blogu <strong> </strong> (složka, která obsahuje složku wp-admin). pokud tento soubor existuje, zobrazí se vistors zpráva <strong> krátce nedostupná pro naplánovanou údržbu. vraťte se za minutu zpět </strong></p> <p>chcete-li zastavit zobrazování zprávy vistors, stačí odstranit soubor <code>.maintenance</code>. automatický upgrade by měl být proveden znovu, jen v případě, že selhal.</p> </blockquote> <p>protože ostatní odpovědi již naznačují, sql server může nebo nemusí explicitně zajistit, že řádky jsou seřazeny v pořadí seskupených indexů před <code>insert</code>.</p><p>to závisí na tom, zda má klastrovaný indexový operátor v plánu sadu vlastností <code>dmlrequestsort</code> (což zase závisí na odhadovaném počtu řádků, které jsou vloženy).</p><p>pokud zjistíte, že sql server to z jakéhokoli důvodu podceňuje, můžete mít prospěch z přidání explicitního <code>order by</code> k dotazu <code>select</code> k minimalizaci rozdělení stránek a následné fragmentaci z operace <code>insert</code></p><p><strong> příklad: </strong></p><pre><code>use tempdb; go create table t(n int primary key,filler char(2000)) create table t2(n int primary key,filler char(2000)) go declare @t table (u uniqueidentifier primary key default newid(),n int) insert into @t(n) select number from master..spt\_values where type = 'p' and number between 0 and 499 /*estimated row count wrong as inserting from table variable*/ insert into t(n) select t1.n*1000 + t2.n from @t t1, @t t2 /*same operation using explicit sort*/ insert into t2(n) select t1.n*1000 + t2.n from @t t1, @t t2 order by t1.n*1000 + t2.n select avg\_fragmentation\_in\_percent, fragment\_count, page\_count, avg\_page\_space\_used\_in\_percent, record\_count from sys.dm\_db\_index\_physical\_stats(2, object\_id('t'), null, null, 'detailed') ; select avg\_fragmentation\_in\_percent, fragment\_count, page\_count, avg\_page\_space\_used\_in\_percent, record\_count from sys.dm\_db\_index\_physical\_stats(2, object\_id('t2'), null, null, 'detailed') ; </code></pre><p>ukazuje, že <code>t</code> je masivně roztříštěný</p><pre><code>avg\_fragmentation\_in\_percent fragment\_count page\_count avg\_page\_space\_used\_in\_percent record\_count      99.3116118225536 92535 92535 67.1668272794663 250000 99.5 200 200 74.2868173956017 92535 0 1 1 32.0978502594514 200 </code></pre><p>ale pro <code>t2</code> fragmentace je minimální</p><pre><code>avg\_fragmentation\_in\_percent fragment\_count page\_count avg\_page\_space\_used\_in\_percent record\_count      0.376 262 62500 99.456387447492 250000 2.1551724137931 232 232 43.2438349394613 62500 0 1 1 37.2374598468001 232 </code></pre><p>naopak někdy budete chtít donutit sql server, aby podceňoval počet řádků, když víte, že data jsou již předem roztříděna a chcete zabránit zbytečnému třídění. jedním z pozoruhodných příkladů je vložení velkého počtu řádků do tabulky pomocí seskupeného indexového klíče <code>newsequentialid</code>. <a href="https://connect.microsoft.com/sqlserver/feedback/details/668540/unnecessary-sort-operation-for-insert-into-clustered-index-with-newsequentialid-key">ve verzích sql serveru před denali sql server přidává zbytečnou a potenciálně nákladnou operaci řazení</a> . tomu lze zabránit</p><pre><code>declare @var int =2147483647 insert into foo select top (@var) * from bar </code></pre><p>sql server poté odhadne, že bude vloženo 100 řádků bez ohledu na velikost <code>bar</code>, která je pod prahem, při kterém je do plánu přidáno řazení. jak je však uvedeno v poznámkách níže, znamená to, že vložka bohužel nebude moci využít výhody minimálního protokolování.</p> <p>v ssms musíte změnit některé možnosti:</p><p>nástroje - možnosti - výsledky dotazu - sql server - výsledky do mřížky (nebo textu) -&gt; <strong>při kopírování nebo ukládání výsledků uveďte záhlaví sloupců</strong>.</p><p>změněná nastavení se použijí na nová, ale ne existující okna dotazů.</p> <p>příkaz <code>merge</code> má složitou syntaxi a ještě složitější implementaci, ale v zásadě jde o spojení dvou tabulek, filtrování dolů na řádky, které je třeba změnit (vložit, aktualizovat nebo smazat), a poté provést požadované změny. vzhledem k těmto vzorovým údajům:</p><pre><code>declare @categoryitem as table ( categoryid integer not null, itemid integer not null, primary key (categoryid, itemid), unique (itemid, categoryid) ); declare @datasource as table ( categoryid integer not null, itemid integer not null primary key (categoryid, itemid) ); insert @categoryitem (categoryid, itemid) values (1, 1), (1, 2), (1, 3), (2, 1), (2, 3), (3, 5), (3, 6), (4, 5); insert @datasource (categoryid, itemid) values (2, 2); </code></pre><p><strong> cíl </strong></p><pre><code>╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 1 ║ 1 ║ ║ 2 ║ 1 ║ ║ 1 ║ 2 ║ ║ 1 ║ 3 ║ ║ 2 ║ 3 ║ ║ 3 ║ 5 ║ ║ 4 ║ 5 ║ ║ 3 ║ 6 ║ ╚════════════╩════════╝ </code></pre><p><strong> zdroj </strong></p><pre><code>╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 2 ║ 2 ║ ╚════════════╩════════╝ </code></pre><p>požadovaným výsledkem je nahrazení dat v cíli daty ze zdroje, ale pouze pro <code>categoryid = 2</code>. po výše uvedeném popisu <code>merge</code> bychom měli napsat dotaz, který spojuje zdroj a cíl pouze na klíče, a filtrovat řádky pouze v klauzulích <code>when</code>:</p><pre><code>merge into @categoryitem as target using @datasource as source on source.itemid = target.itemid and source.categoryid = target.categoryid when not matched by source and target.categoryid = 2 then delete when not matched by target and source.categoryid = 2 then insert (categoryid, itemid) values (categoryid, itemid) output $action, isnull(inserted.categoryid, deleted.categoryid) as categoryid, isnull(inserted.itemid, deleted.itemid) as itemid ; </code></pre><p>to dává následující výsledky:</p><pre><code>╔═════════╦════════════╦════════╗ ║ $action ║ categoryid ║ itemid ║ ╠═════════╬════════════╬════════╣ ║ delete ║ 2 ║ 1 ║ ║ insert ║ 2 ║ 2 ║ ║ delete ║ 2 ║ 3 ║ ╚═════════╩════════════╩════════╝ ╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 1 ║ 1 ║ ║ 1 ║ 2 ║ ║ 1 ║ 3 ║ ║ 2 ║ 2 ║ ║ 3 ║ 5 ║ ║ 3 ║ 6 ║ ║ 4 ║ 5 ║ ╚════════════╩════════╝ </code></pre><p>realizační plán je: <img src="https://i.stack.imgur.com/fovhu.jpg" alt="merge plan"></p><p>všimněte si, že jsou obě tabulky plně naskenovány. můžeme to považovat za neefektivní, protože pouze řádky, kde <code>categoryid = 2</code> bude ovlivněno v cílové tabulce. zde přicházejí varování v books online. jeden chybný pokus o optimalizaci, aby se dotkl pouze nezbytných řádků v cíli, je:</p><pre><code>merge into @categoryitem as target using ( select categoryid, itemid from @datasource as ds where categoryid = 2 ) as source on source.itemid = target.itemid and target.categoryid = 2 when not matched by target then insert (categoryid, itemid) values (categoryid, itemid) when not matched by source then delete output $action, isnull(inserted.categoryid, deleted.categoryid) as categoryid, isnull(inserted.itemid, deleted.itemid) as itemid ; </code></pre><p>logika v klauzuli <code>on</code> je použita jako součást spojení. v tomto případě je spojení úplným vnějším spojením (viz <a href="http://technet.microsoft.com/en-us/library/bb522522%28v=sql.105%29.aspx">tento záznam books online</a> proč). použití kontroly kategorie 2 na cílových řádcích jako součásti vnějšího spojení nakonec povede k odstranění řádků s jinou hodnotou (protože neodpovídají zdroji):</p><pre><code>╔═════════╦════════════╦════════╗ ║ $action ║ categoryid ║ itemid ║ ╠═════════╬════════════╬════════╣ ║ delete ║ 1 ║ 1 ║ ║ delete ║ 1 ║ 2 ║ ║ delete ║ 1 ║ 3 ║ ║ delete ║ 2 ║ 1 ║ ║ insert ║ 2 ║ 2 ║ ║ delete ║ 2 ║ 3 ║ ║ delete ║ 3 ║ 5 ║ ║ delete ║ 3 ║ 6 ║ ║ delete ║ 4 ║ 5 ║ ╚═════════╩════════════╩════════╝ ╔════════════╦════════╗ ║ categoryid ║ itemid ║ ╠════════════╬════════╣ ║ 2 ║ 2 ║ ╚════════════╩════════╝ </code></pre><p>kořenová příčina je ze stejného důvodu, proč se predikáty chovají v klauzuli vnější spojení <code>on</code> odlišně, než když jsou specifikovány v klauzuli <code>where</code>. syntaxe <code>merge</code> (a implementace spojení v závislosti na zadaných klauzulích) jen ztěžují vidět, že tomu tak je.</p><p> <a href="http://technet.microsoft.com/en-us/library/bb510625%28v=sql.105%29.aspx">navádění v books online</a> (rozšířeno v položce <a href="http://technet.microsoft.com/en-us/library/cc879317%28v=sql.105%29.aspx">optimizing performance</a> ) nabízí navádění, které zajistí, že správná sémantika je vyjádřena pomocí syntaxe <code>merge</code>, aniž by uživatel nutně musel muset pochopit všechny podrobnosti implementace nebo zohlednit způsoby, kterými by optimalizátor mohl legitimně přeskupit věci z důvodů efektivnosti provádění.</p><p>dokumentace nabízí tři možné způsoby implementace časného filtrování:</p><p><strong> zadání podmínky filtrování v klauzuli <code>when</code> </strong> zaručuje správné výsledky, ale může znamenat, že více řádků je čteno a zpracováno ze zdroje a cíle tabulky, než je nezbytně nutné (viz první příklad).</p><p><strong> aktualizace prostřednictvím zobrazení </strong>, která obsahuje podmínku filtrování, také zaručuje správné výsledky (protože změněné řádky musí být přístupné pro aktualizaci prostřednictvím zobrazení), ale vyžaduje to vyhrazené zobrazení, které splňuje liché podmínky pro aktualizaci zobrazení.</p><p><strong> použití společného výrazu tabulky </strong> přináší podobné riziko při přidávání predikátů k klauzuli <code>on</code>, ale z poněkud odlišných důvodů. v mnoha případech to bude bezpečné, ale vyžaduje to odbornou analýzu prováděcího plánu, aby se to potvrdilo (a rozsáhlé praktické testování). například:</p><pre><code>with target as ( select * from @categoryitem where categoryid = 2 ) merge into target using ( select categoryid, itemid from @datasource where categoryid = 2 ) as source on source.itemid = target.itemid and source.categoryid = target.categoryid when not matched by target then insert (categoryid, itemid) values (categoryid, itemid) when not matched by source then delete output $action, isnull(inserted.categoryid, deleted.categoryid) as categoryid, isnull(inserted.itemid, deleted.itemid) as itemid ; </code></pre><p>výsledkem jsou správné výsledky (neopakované) s optimálnějším plánem:</p><p><img src="https://i.stack.imgur.com/tazmk.jpg" alt="merge plan 2"></p><p>plán čte pouze řádky pro kategorii 2 z cílové tabulky. to může být důležitým hlediskem výkonu, pokud je cílová tabulka velká, ale je příliš snadné tuto chybu získat pomocí syntaxe <code>merge</code>.</p><p>někdy je snazší zapsat <code>merge</code> jako samostatné operace dml. tento přístup může dokonce <strong> vést lépe </strong> než jediný <code>merge</code>, což je skutečnost, která lidi často překvapuje.</p><pre><code>delete ci from @categoryitem as ci where ci.categoryid = 2 and not exists ( select 1 from @datasource as ds where ds.itemid = ci.itemid and ds.categoryid = ci.categoryid ); insert @categoryitem select ds.categoryid, ds.itemid from @datasource as ds where ds.categoryid = 2; </code></pre> <p><strong> aktualizace leden 2017 - sql server 2016+/azure sql database </strong></p><p>sql server 2016 a aktuální verze azure sql database má nyní následující syntaxi pro funkce, procedury, tabulky, databáze atd. ( <a href="https://blogs.msdn.microsoft.com/sqlserverstorageengine/2015/11/03/drop-if-exists-new-thing-in-sql-server-2016/"><code>drop if exists</code></a> ):</p><pre><code>drop function if exists dbo.fn\_myfunc; </code></pre><p>a sql server 2016 service pack 1 přidává ještě lepší funkčnost pro moduly (funkce, procedury, spouštěče, zobrazení), což znamená, že nedochází ke ztrátě oprávnění nebo závislostí ( <a href="https://blogs.msdn.microsoft.com/sqlserverstorageengine/2016/11/17/create-or-alter-another-great-language-enhancement-in-sql-server-2016-sp1/"><code>create or alter</code></a> ):</p><pre><code>create or alter function dbo.fn\_myfunc ... </code></pre><p>obě tato vylepšení syntaxe mohou vést k mnohem jednodušším skriptům používaným pro řízení zdroje, nasazení atd.</p><p>ale pokud používáte ...</p><hr><p><strong> starší verze </strong></p><p>při skriptu z management studio je třeba udělat to, co sql server dělá:</p><pre><code>if not exists (select 1 from sys.objects where type = 'fn' and name = 'fn\_myfunc') begin declare @sql nvarchar(max); set @sql = n'create function ...'; exec sp\_executesql @sql; end </code></pre><p>nebo můžete říct:</p><pre><code>begin try drop function dbo.fn\_myfunc; end try begin catch print 'function did not exist.'; end catch go create function... </code></pre><p>nebo můžete jen říct:</p><pre><code>drop function dbo.fn\_myfunc; go create function... </code></pre><p>(zde se zobrazí chybová zpráva, pokud funkce již neexistuje, ale skript bude pokračovat od příštího go, takže ať už kapka pracovala nebo ne, bude funkce stále vytvořena (znovu).)</p><p>pokud funkci zrušíte a znovu ji vytvoříte, ztratíte také oprávnění a informace o závislostech.</p> <p>děláme to úplně na <a href="http://smartystreets.com">smartystreets</a> . uživatelé nahrávají soubory s potenciálně miliony adres v nich a my je ověřujeme a standardizujeme/duplikujeme, atd. je to velmi náročné na procesor a dokonce i s kmenovými daty načtenými na jednotku ram, miliony adres zabere několik hodin (mimochodem, pro tuto částku je to velmi rychlé ...).</p><p>může být také důležité navrhnout uživatelské rozhraní, které může podporovat desítky úloh spuštěných paralelně. například naše serverové uzly se rozšiřují a můžeme podporovat mnoho souborů najednou. uživatelé budou potřebovat efektivní způsob, jak zobrazit stav a spravovat je. v roce 2011 jsme vylepšili naše uživatelské rozhraní a to je to, s čím jsme přišli.</p><hr><p> <a href="http://youtu.be/qdjsolatz4u?hd=1">zde je 30sekundové video</a> ukazující, jak celý proces funguje a jak rozhraní reaguje na aktuální stav úlohy (úloh). pokud chcete, můžete vyzkoušet sami od <a href="http://smartystreets.com/account/create">tato stránka</a> (zdarma, nebojte se ...).</p><hr><p>screenshoty pracovního postupu ... trvá asi 30 sekund až několik minut, v závislosti na vašich souborech.</p><p><img src="https://i.stack.imgur.com/egatr.png" alt="upload list"></p><p><em> nahrajte svůj seznam </em></p><p><img src="https://i.stack.imgur.com/kqkb9.png" alt="see the file uploading"></p><p><em> viz nahrání souboru </em></p><p><img src="https://i.stack.imgur.com/zv26q.png" alt="map the fields"></p><p><em> mapujte pole (probíhá automaticky; stačí potvrdit, že automatická mapa byla správná) </em></p><p><img src="https://i.stack.imgur.com/wodst.png" alt="stay up-to-date with the current status"></p><p><em> zůstaňte v kontaktu s tím, co se nyní děje </em></p><hr><p>všimněte si, že jakmile seznam začne zpracovávat, uživatel se může vrátit a nahrát více, které seznamy budou zpracovány paralelně v reálném čase. seznamy lze kdykoli zrušit/smazat a po dokončení je lze stáhnout. pokud byl seznam stažen alespoň jednou, zobrazí se zaškrtnutí.</p><p>toto je vlastně stárnoucí návrh, který plánujeme upgradovat. bude se to cítit spíš jako moderní, responzivní webová aplikace.</p><p>ještě stojí za zmínku, že jsme mnohokrát změnili vzhled stránky „dashboard“ účtu a tento návrh inicioval nejmenší volání/e-maily podpory a zákazníci to rádi viděli na první pohled. první uživatelé mají tendenci shledávat, že se s ním dostanou docela rychle.</p> <h2>souhrn</h2><p>nechte propojený server dělat co nejvíce.<br> je <em> nemožné </em> pro sql server optimalizovat dotaz na propojeném serveru, dokonce i na jiném serveru sql</p><h2>dlouho</h2><p>klíčovým faktorem je <em> kde </em> je dotaz spuštěn.</p><p>v tomto případě se jedná o triviální výběr, takže všechny řádky z tabulky budou odeslány po drátu. nezáleží na tom.</p><p>když přidáte připojení a kde, pak na tom může záležet. chcete, aby sql server umožnil propojenému serveru provést co největší filtrování, aby se zmenšila velikost dat přicházejících po síti.</p><p>například druhý případ by zde měl být efektivnější.</p><pre><code>select * from openquery(&lt;linked server&gt;, 'select &lt;column list&gt; from mytable') t1 join somelocaltable t2 on ... where t1.foo = 'bar' select * from openquery(&lt;linked server&gt;, 'select &lt;column list&gt; from mytable where foo = ''bar''') join somelocaltable t2 on ... </code></pre><p>omezení openquery je v tom, že nemůžete parametrizovat: proto potřebujete dynamický sql, abyste mohli přidat klauzule where atd.</p><p>výkon propojených serverů může být ovlivněn <a href="http://msdn.microsoft.com/en-us/library/ms178532.aspx"><code>sp\_serveroption</code></a> . nastavení <code>collation compatible</code> říká vše</p><blockquote> <p>pokud je tato možnost nastavena na true, sql server předpokládá, že všechny znaky na propojeném serveru jsou kompatibilní s místním serverem, pokud jde o znakovou sadu a pořadí řazení (nebo pořadí řazení). to umožňuje serveru sql server odesílat porovnání sloupců znaků zprostředkovateli. pokud tato možnost není nastavena, sql server vždy vyhodnocuje porovnání na sloupcích znaků místně.</p> </blockquote><p>to znamená, zkuste nenechat sql server zpracovat data místně.</p><p>poznámka: na mé <code>foo = 'bar'</code> druhý příklad výše je filtr odeslán na propojený server, protože je to pouze řetězcová konstanta na sql server. skutečná klauzule where v prvním příkladu může nebo nemusí být zaslána vzdáleně.</p><p>nakonec jsem také zjistil, že rozložení dat do dočasné tabulky a jejich připojení k místním tabulkám je často lepší než připojení přímo k openquery.</p>