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:
- Wenn ich in SSMS diese Pseudoabfrage ausführe, ist
SELECT * FROM (L1.V1 u L2.V2 u L3.V3) WHERE some filters
die Leistung wirklich großartig - 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 filters
die 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?
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 ichmaster
. In derserver roles
Registerkarte wähle ichpublic
. inUser mapping
Registerkarte ich die beteiligten Datenbanken in Remote - Abfragen und für jeden von ihnen, ich wähledb_ddladmin
undpublic
Rolle. 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 vieleALTER
und vieleCREATE
Berechtigungen, jedoch nicht SHOW PLAN (dann habe ich auch diese ausgewählt).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 ichlocal user sa
undremote user linkedserver
mit 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:
den Ausführungsplan mit der Ansicht:
Antworten:
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'
aufcognome = 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
NVARCHAR
zuVARCHAR
, 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 Function
SQL 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:
Die Abfrage lautet dann:
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 :)quelle
SELECT * FROM fn_anagrafiche2()
? Funktioniert eine Auswahl aus dieser Ansicht besser?AND 1 = 1
Sie sie einfach Ihrem Filter hinzu. Kann Ihre App das tun?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 :
sysadmin
Serverrolledb_owner
oderdb_ddladmin
DatenbankrolleNormalerweise 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:
Gewähren Sie die
linked_server
Kontoberechtigungen wiedb_ddladmin
auf dem Remoteserver (damit Statistiken angezeigt werden).Verweigern Sie das Konto, das alles
db_ddladmin
tatsä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!
quelle