SQL Server - Verbindungsserver und Abfrageleistung


7

Ich habe ein Leistungsproblem im Zusammenhang mit SQL Server / Verbindungsservern / Ansichten. Ich hoffe, Sie können mir helfen zu verstehen, wie ich am besten tun kann, was ich will =).

  • Ich habe eine Datenbank K mit 3 Verbindungsservern L1, L2, L3 bis 3 Datenbanken X, Y, Z.
  • In X, Y, Z i gibt es jeweils 3 Ansichten, die als V1, V2, V3 bezeichnet werden.
  • Ich möchte die Vereinigung von V1, V2, V3 nach Datenbank K mit dem Verbindungsserver L1, L2, L3 abfragen.

Nach einigen Tests ist dies die Situation:

  1. Wenn ich in SSMS diese Pseudoabfrage ausführe, ist SELECT * FROM (L1.V1 u L2.V2 u L3.V3) WHERE some filtersdie Leistung wirklich großartig
  2. Wenn ich eine Ansicht VK in der Datenbank K erstelle, die die Vereinigung der drei Ansichten enthält, und dann die Abfrage ausführe, ist SELECT * FROM VK WHERE some filtersdie Leistung schlechter als in Fall 1

Fragen

  • Warum ist die Leistung so unterschiedlich?
  • Wie kann ich die Leistung in Fall 2 verbessern?

Ich bin daran interessiert, die Leistung in Fall 2 zu verbessern, da ich eine Ansicht benötige, um sie mit nHbinernate in unserer Software abzubilden ...

Vielen Dank im Voraus, Grüße

UPDATE NACH JOHN ALANS POST

Ok, ich versuche es aber ohne Ergebnisse. Ich bin kein DBA und meine Fähigkeiten zur DB-Konfiguration sind sehr begrenzt. Können wir Schritt für Schritt fortfahren?

  1. Auf dem Remote-Server ( called Y) habe ich ein neues Konto ( called linkedserver) über Sicherheit-> Anmeldungen-> Neue Anmeldung erstellt. Ich wähle den Anmeldenamen und dann die SQL-Authentifizierung und ein Passwort. für Deafault-Datenbank wähle ich master. In der server rolesRegisterkarte wähle ich public. in User mappingRegisterkarte ich die beteiligten Datenbanken in Remote - Abfragen und für jeden von ihnen, ich wähle db_ddladminund publicRolle. Dann habe ich für jede Datenbank, die an einer Remote-Abfrage beteiligt ist, die effektive Berechtigung für den Benutzer des Verbindungsservers überprüft, und es gibt viele ALTERund viele CREATEBerechtigungen, jedoch nicht SHOW PLAN (dann habe ich auch diese ausgewählt).

  2. Auf dem Datenbankserver ( called X), auf dem der mit Y verbundene Verbindungsserver vorhanden ist, habe ich einen Verbindungsserver ( called L1) erstellt. In der Sicherheits-TAB habe ich local user saund remote user linkedservermit seinem Passwort ausgewählt.

Wenn ich die Abfrage über L1 ohne VIEW ausführe, habe ich ein gutes Ergebnis. Wenn ich die Abfrage in eine VIEW mit geringer Leistung stelle, hat sich nichts geändert ...

Ich glaube, ich habe einen Schritt falsch gemacht, aber ich weiß nicht, wo ...

FÜR BESSERE KLARHEIT

Dies ist die Abfrage, die ich ohne Ansicht über einen Verbindungsserver ausführe:

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'

In die Ansicht habe ich nur diesen Code eingefügt

    select * from dolph.agendasdn.dbo.vistaaccettazionegrp
    union
    select * from dolph.acampanet.dbo.vistaaccettazionegrp
    union
    select * from municipio.dbnet.dbo.vistaaccettazionegrp

dann habe ich angerufen select * from VIEW where cognome = 'test' and nome = 'test'

Damit..

  • 1. Fall 0-1 Sekunden.
  • 2. Fall> 15 Sekunden ...

Ich finde das absurd!

AUSFÜHRUNGSPLAN

Der Ausführungsplan mit einfacher Abfrage ohne Verwendung einer Ansicht: Geben Sie hier die Bildbeschreibung ein

den Ausführungsplan mit der Ansicht: Ausführungsplan mit Ansicht


Bitte veröffentlichen Sie Ihren Hinrichtungsplan für jeden Fall
Roi Gavish

Antworten:


5

Ihr Problem beginnt und endet mit Statistiken und Schätzungen. Ich habe Ihre Situation auf meinen Servern reproduziert und einige interessante Hinweise und eine Problemumgehungslösung gefunden.

Schauen
wir uns zunächst Ihren Ausführungsplan an: Wenn eine Ansicht verwendet wird, können wir sehen, dass ein Filter angewendet wird, nachdem die Remote-Abfrage ausgeführt wurde, während ohne die Ansicht überhaupt kein Filter angewendet wurde. Die Wahrheit ist, dass der Filter in der Remote-Abfrage auf dem Remote-Server angewendet wurde , bevor die Daten über das Netzwerk abgerufen wurden.
Nun, offensichtlich ist es besser, den Filter auf dem Remote-Server anzuwenden und damit weniger Daten abzurufen, und das passiert natürlich nur, wenn keine Ansicht verwendet wird.

Also ... was ist so interessant ...?

Als ich den Filter von cognome = 'test'auf cognome = N'test'(Unicode-Darstellung der Zeichenfolge) änderte, verwendete die Ansicht überraschenderweise denselben Ausführungsplan wie die erste Abfrage.
Ich denke , der Grund , dass irgendwie ist , wenn die Ansicht SQL Server geschätzt mit , dass es eine kleine Anzahl von Zeilen seiner Rückkehr aus der (remote) Abfrage, und dass eine lokale Filterung wird billiger, aber wenn SQL Server implizit konvertieren mußten NVARCHARzu VARCHAR, Statistiken konnten nicht mehr verwendet werden und die Entscheidung, lokal zu filtern, wurde nicht getroffen.
Ich habe lokal nach den Statistiken gesucht, aber die Ansicht hatte keine Statistiken. Ich vermute also, dass die Ansicht die Remote-Statistiken so verwendet, wie es eine Ad-hoc-Abfrage nicht tut, und dann die falsche Entscheidung trifft.

OK, was löst das Problem?

Ich habe vorhin festgestellt, dass es eine Problemumgehung gibt (zumindest bis jemand eine bessere Lösung findet), und nein, ich meine nicht, Unicode für Ihre Zeichenfolgen zu verwenden.
Ich wollte zuerst eine Antwort geben, ich muss immer noch herausfinden, warum, aber wenn ich einen Inline FunctionSQL Server verwende, verhält es sich genauso wie bei der Abfrage (ohne Ansicht). Wenn Sie also die Ansicht durch die Funktion ersetzen, erhalten Sie auf einfache Weise das gleiche Ergebnis Abfrage und mit guter Leistung (zumindest in meiner Umgebung).

Mein Code-Vorschlag für Sie lautet:

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

Die Abfrage lautet dann:

SELECT * 
FROM fn_anagrafiche2()
WHERE cognome = 'prova'

Dies funktioniert auf meinen Servern, aber natürlich testen Sie es zuerst.
Hinweis: Ich empfehle die Verwendung SELECT *überhaupt nicht, da es für zukünftige Fehler anfällig ist. Ich habe es einfach verwendet, weil es in Ihrer Frage war und ich das nicht ändern musste, wenn ich stattdessen diese Bemerkung hinzufügen kann :)


Zunächst einmal vielen Dank! Ich versuche es mit N'sometext 'im Filter der VIEW-Abfrage und arbeite wie du sagst und es ist fantastisch! Wie ich in der Frage sage, kann ich eine Funktion jedoch nicht direkt verwenden, da ich programmgesteuert ein ORM-Framework (Ruhezustand) verwenden muss, das nur Tabellen und Ansichten aus der Datenbank direkt zuordnen kann. Wie kann ich das also ausdrücken? nützliche Informationen (ich meine Unicode-Zeichenfolge) in einer Ansicht? Ich muss alle Zeichenfolgenspalten in der Ansicht auf dem Remote-Server konvertieren (vistaangraficagrp ist eine Ansicht auf dem Remote-Server).
Abgabe am

@ced Das wird unangenehm, aber was ist, wenn Sie die Funktion erstellen und dann eine lokale Ansicht mit erstellen SELECT * FROM fn_anagrafiche2()? Funktioniert eine Auswahl aus dieser Ansicht besser?
Roi Gavish

Und man kann lesen wollen dies auch.
Roi Gavish

Wenn ich eine lokale Ansicht mit der Auswahl * aus fn_anagrafiche2 () (die die Union enthält) erstelle, ist die Leistung dieselbe wie in dem Fall, in dem die Union direkt in der Ansicht ist ... also leider keine bessere Leistung in diesem Fall ... = (
am

@ced Vergessen Sie dann die Funktion, fügen AND 1 = 1Sie sie einfach Ihrem Filter hinzu. Kann Ihre App das tun?
Roi Gavish

2

Bei Verbindungsservern und Statistiken gibt es eine grundlegende Einschränkung: Sie können sie nur anzeigen, wenn Sie über eine der folgenden Berechtigungen für den Remotestandort verfügen :

  • ein Mitglied der sysadminServerrolle
  • ein Mitglied der db_owneroder db_ddladminDatenbankrolle
  • Objektbesitzer

Normalerweise sind Sie nur ein Datenleser, der keine Statistiken (nicht einmal Histogramme) sehen kann. Ausführungspläne neigen dann dazu zu leiden.

Dies wurde in SQL Server 2012 SP1 behoben, aber es ist für älteren Code, der auf älteren Versionen ausgeführt wird, nicht angenehm.

Der Trick, den ich mache, ist wie folgt:

  1. Gewähren Sie die linked_serverKontoberechtigungen wie db_ddladminauf dem Remoteserver (damit Statistiken angezeigt werden).

  2. Verweigern Sie das Konto, das allesdb_ddladmintatsächlich gewährt:

    CREATE TABLE

    CREATE VIEW

    CREATE PROCEDURE

    CREATE FUNCTION

    CREATE RULE

usw.

Es funktioniert wie ein Zauber, ohne die Sicherheit zu beeinträchtigen!


Die vollständige Liste der Berechtigungen, die für die Rolle db_ddladmin erteilt wurden, finden Sie HIER
Roi Gavish

Ich verstehe nicht sehr gut. Betrachten Sie nur einen Remote-Server und nur einen Verbindungsserver. Auf einem Remote-Server benötige ich ein Konto mit aktivierter Benutzerrolle db_ddladmin, das der Datenbank zugeordnet ist? In der Datenbank mit Verbindungsserver muss ich den auf dem Remoteserver erstellten Benutzer auf der Registerkarte Berechtigung des Verbindungsservers angeben.
Abgegeben am

Ja - das Konto, das zum Lesen auf dem Remoteserver verwendet wird, muss auch ddl_admin auf dem Remoteserver haben. Andernfalls werden die Statistiken nicht angezeigt (dbcc show_statistics läuft hinter den Kulissen, Sie können sie im Profiler sehen)
John Alan

Frage aktualisiert mit einigen Tests, die ich durchgeführt habe, ohne Ergebnisse ...
ced

@JohnAlan Wenn er keine Statistiken sehen kann, warum sollte es dann einen Leistungsunterschied zwischen den beiden Fällen geben (mit und ohne Ansicht)?
Roi Gavish
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.