Szenario: SQL Server 2014 (v12.0.4100.1)
Der .NET-Dienst führt diese Abfrage aus:
SELECT name, base_object_name
FROM sys.synonyms
WHERE schema_id IN (SELECT schema_id
FROM sys.schemas
WHERE name = N'XXXX')
ORDER BY name
... was ungefähr 6500 Zeilen zurückgibt, aber oft nach mehr als 3 Minuten eine Zeitüberschreitung aufweist. Das XXXX
obige ist nicht 'dbo'.
Wenn ich diese Abfrage in SSMS als UserA ausführe, wird die Abfrage in weniger als einer Sekunde zurückgegeben.
Bei Ausführung als UserB (wie der .NET-Dienst eine Verbindung herstellt) dauert die Abfrage 3-6 Minuten und die CPU% liegt die ganze Zeit über bei 25% (von 4 Kernen).
UserA ist eine Domänenanmeldung in der Sysadmin-Rolle.
UserB ist ein SQL Login mit:
EXEC sp_addrolemember N'db_datareader', N'UserB'
EXEC sp_addrolemember N'db_datawriter', N'UserB'
EXEC sp_addrolemember N'db_ddladmin', N'UserB'
GRANT EXECUTE TO [UserB]
GRANT CREATE SCHEMA TO [UserB]
GRANT VIEW DEFINITION TO [UserB]
Ich kann dies in SSMS duplizieren, indem ich das obige SQL in einen Execute as...Revert
Block einbinde , sodass der .NET-Code nicht im Bild ist.
Der Ausführungsplan sieht gleich aus. Ich habe das XML unterschieden und es gibt nur geringfügige Unterschiede (CompileTime, CompileCPU, CompileMemory).
Alle E / A-Statistiken zeigen keine physischen Lesevorgänge an:
Tabelle 'sysobjvalues'. Scananzahl 0, logische Lesevorgänge 19970, physische Lesevorgänge 0, Vorauslesevorgänge 0, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0. Tabelle 'Arbeitsdatei'. Scananzahl 0, logische Lesevorgänge 0, physische Lesevorgänge 0, Vorauslesevorgänge 0, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0. Tabelle 'Arbeitstisch'. Scananzahl 0, logische Lesevorgänge 0, physische Lesevorgänge 0, Vorauslesevorgänge 0, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0. Tabelle 'sysschobjs'. Scananzahl 1, logische Lesevorgänge 9122, physische Lesevorgänge 0, Vorauslesevorgänge 0, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0. Tabelle 'sysclsobjs'. Scananzahl 0, logische Lesevorgänge 2, physische Lesevorgänge 0, Vorauslesevorgänge 0, Lob-Lesevorgänge 0, Lob-Lesevorgänge 0, Lobvorlesevorgänge 0.
Der Status von XEvent wartet (für eine ~ 3-minütige Abfrage):
+ --------------------- + ------------ + -------------- -------- + ------------------------------ + ---------- ------------------- + | Warten Sie Typ | Warte Zählung | Gesamtwartezeit (ms) | Wartezeit der gesamten Ressource (ms) | Gesamtsignalwartezeit (ms) | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- + | SOS_SCHEDULER_YIELD | 37300 | 427 | 20 | 407 | | NETWORK_IO | 5 | 26 | 26 | 0 | | IO_COMPLETION | 3 | 1 | 1 | 0 | + --------------------- + ------------ + -------------- -------- + ------------------------------- + --------- -------------------- +
Wenn ich die Abfrage neu schreibe (in SSMS habe ich keinen Zugriff auf den App-Code) an
declare @id int
SELECT @id=schema_id FROM sys.schemas WHERE name = N'XXXX'
SELECT a.name, base_object_name FROM sys.synonyms a
WHERE schema_id = @id
ORDER BY name
dann läuft UserB mit der gleichen (schnellen) Geschwindigkeit wie UserA.
Wenn ich db_owner
zu UserB hinzufüge , wird die Abfrage erneut <1 Sek. Ausgeführt.
Über diese Vorlage erstelltes Schema:
DECLARE @TranName VARCHAR(20)
SELECT @TranName = 'MyTransaction'
BEGIN TRANSACTION @TranName
GO
IF NOT EXISTS (SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = '{1}')
BEGIN
EXEC('CREATE SCHEMA [{1}]')
EXEC sp_addextendedproperty @name='User', @value='{0}', @level0type=N'Schema', @level0name=N'{1}'
END
GO
{2}
COMMIT TRANSACTION MyTransaction;
GO
Und {2} ist meiner Meinung nach eine Liste von Synonymen, die in diesem Schema erstellt wurden.
Abfrageprofil an zwei Stellen in der Abfrage:
Ich habe ein Ticket bei Microsoft geöffnet.
Außerdem haben wir versucht, UserB hinzuzufügen db_owner
und dann DENY
alle uns bekannten Berechtigungen zu verwenden, die damit verbunden sind db_owner
. Das Ergebnis ist eine schnelle Abfrage. Entweder haben wir etwas verpasst (durchaus möglich) oder es gibt eine spezielle Überprüfung für die db_owner
Rolle.
access check cache bucket count
undaccess check cache quota
Konfigurationsoptionen vorher nicht. Muss ein bisschen damit rumspielen.WHILE(1=1) BEGIN DBCC FREESYSTEMCACHE ('TokenAndPermUserStore') WAITFOR DELAY '00:00:05' END
in einer Schleife laufe , wird die Abfrage in weniger als 2 Minuten gegenüber 8 Minuten abgeschlossen.Wenn dies noch aktiv ist - wir hatten das gleiche Problem -, scheint es, dass wenn Sie entweder der Dbo oder ein Systemadministrator sind, jeder Zugriff auf sys.objects (oder ähnliches) sofort erfolgt, ohne dass einzelne Objekte überprüft werden müssen.
Wenn es sich um einen niedrigen db_datareader handelt, muss er jedes Objekt der Reihe nach überprüfen ... es ist im Abfrageplan versteckt, da sich diese eher wie Funktionen als wie Ansichten / Tabellen verhalten
Der Plan sieht gleich aus, aber er macht verschiedene Dinge hinter der Haube
quelle
Die Verwendung des Trace-Flags 9481 scheint dieses Problem für mich zu beheben.
Der CE (Cardinality Estimator) von 2014 (kompatibel 120) wurde von 2012 bis 2008 geändert, und unter Verwendung von TF 9481 wird der CE 2012 erzwungen.
Siehe Der SQL 2014 Cardinality Estimator isst schlechtes TSQL zum Frühstück von Kendra Little.
quelle