Ich versuche, die Ergebnismenge einzufügen aus:
SELECT * FROM sys.database_scoped_configurations
in eine temporäre Tabelle, weil ich die Einstellungen für alle Datenbanken auf meinem Server überprüfen möchte. Also habe ich diesen Code geschrieben:
DROP TABLE IF EXISTS #h
CREATE TABLE #h(dbname sysname, configuration_id INT, name sysname, value SQL_VARIANT, value_for_secondary SQL_VARIANT)
EXEC sys.sp_MSforeachdb 'USE ?; insert into #h(dbname, configuration_id, name, value,value_for_secondary) SELECT ''?'' as dbname, * FROM sys.database_scoped_configurations D'
SELECT * FROM #h H
Aber dann gibt es nur eine Zeile pro Datenbank, nicht die vier Zeilen, die ich von einer einfachen Auswahl in jeder Datenbank erwarte.
Ich weiß, dass es bessere Möglichkeiten gibt, dies zu codieren, als sp_MSForEachDB zu verwenden, und ich habe mehrere ausprobiert. Aber ich bekomme immer noch nur eine Zeile pro Datenbank. Ich habe dies sowohl auf SQL Server 2016 RTM als auch auf SP1 versucht
Ist dies ein Fehler mit SQL Server 2016 oder mache ich etwas falsch?
sql-server
configuration
sql-server-2016
Henrik Staun Poulsen
quelle
quelle
Antworten:
Ja. Dies ist definitiv kein korrektes Verhalten. Ich habe es hier gemeldet und ist in SQL Server 2016 SP2 CU9 behoben .
Wie Mikael Eriksson in den Kommentaren sagt
sys.database_scoped_configurations
undsys.dm_exec_sessions
als Ansichten im Format implementiert sindBeim Vergleich der beiden folgenden Pläne ergibt sich jedoch ein offensichtlicher Unterschied.
Die Ausgabe des Ablaufverfolgungsflags 8619 für diese beiden Abfragen wird angezeigt
SQL Server kann anscheinend nicht feststellen, dass die Quelle für die TVF nicht auch das Einfügeziel ist, sodass ein Halloween-Schutz erforderlich ist.
Im Sitzungsfall wurde dies als Spool implementiert, der zuerst alle Zeilen erfasst. In der
database_scoped_configurations
durch Hinzufügen eines aTOP 1
zum Plan. Die VerwendungTOP
für den Halloween-Schutz wird in diesem Artikel erläutert . Der Artikel erwähnt auch ein undokumentiertes Trace-Flag, um eine Spool zu erzwingen, anstattTOP
dass dies wie erwartet funktioniert.Ein offensichtliches Problem bei der Verwendung
TOP 1
anstelle einer Spool besteht darin, dass die Anzahl der eingefügten Zeilen willkürlich begrenzt wird. Dies wäre also nur gültig, wenn die Anzahl der von der Funktion zurückgegebenen Zeilen <= 1 wäre.Das erste Memo sieht so aus
Vergleichen Sie dies mit dem ursprünglichen Memo für Abfrage 2
Wenn ich das oben Gesagte richtig verstehe, denke ich, dass die erste TVF maximal eine Zeile zurückgeben kann und wendet daher eine falsche Optimierung an. Das Maximum für die zweite Abfrage wird auf
1.34078E+154
(2^512
) gesetzt.Ich habe keine Ahnung, woher diese maximale Zeilenanzahl stammt. Vielleicht Metadaten vom Autor der DMV? Es ist auch seltsam, dass die
TOP(50)
Problemumgehung nicht umgeschrieben wird,TOP(1)
daTOP(50)
dies das Auftreten des Halloween-Problems nicht verhindern würde (obwohl es auf unbestimmte Zeit fortgesetzt werden würde).quelle
Bitte hören Sie auf zu benutzen
sp_MSForEachDB
. Es wird nicht unterstützt, ist nicht dokumentiert und fehlerhaft - was hier das Problem sein kann. Mein Ersatz zeigt hier das gleiche Problem, aber im Allgemeinen ist es sicherer zu verwenden.Für solche Dinge ziehe ich es vor, dynamisches SQL zu generieren, als einen einzelnen Befehl an eine Prozedur zu übergeben, um ihn mehrmals auszuführen (sogar meine Prozedur, der ich viel mehr vertraue). Auf diese Weise kann ich einfach die Befehle drucken, anstatt sie auszuführen, und Stellen Sie sicher, dass sie alle tun, was sie sagen.
Ausgehend von der Beobachtung, dass der der Systemansicht zugrunde liegende Code a implementiert
TOP (1)
, können wir Folgendes versuchen:Beachten Sie, dass ich
USE
hier nicht verwende , sondern dersys
Katalogansicht den Datenbanknamen voranstelle .Warum die Ansicht auf magische Weise funktioniert, weiß ich nicht. Ich weiß nicht, dass Sie hier eine gute Antwort erhalten, da wahrscheinlich Kommentare von Microsoft (oder von Personen, die Zugriff auf den Quellcode haben oder bereit sind, einen Debugger zu starten) erforderlich sind.
quelle
Vielen Dank, dass Sie dieses Problem gemeldet haben!
Dies ist in der Tat ein Fehler in der Art und Weise, wie das Abfrageoptimierungsprogramm einen Plan für die
sys.database_scoped_configurations
Katalogansicht generiert . Wir werden dies bei einem der nächsten Updates von SQL Server 2016 und in der Azure SQL-Datenbank beheben.Um dieses Problem zu umgehen, können Sie eine
TOP
KlauselSELECT
seitens Ihrer Einfügung hinzufügen , um den richtigen Plan zu erhalten, z.quelle
Ich bin damit einverstanden, dass dies sehr seltsam und ein potenzieller Fehler ist, aber wenn Sie Ihrer Auswahl beispielsweise ein TOP (50) hinzufügen, werden tatsächlich alle Zeilen zurückgegeben, sodass Sie zumindest in Fahrt kommen. Das Ergebnis scheint von einer Systemtabellenwertfunktion ([DB_SCOPED_CONFIG]) zu stammen, daher kann ich nicht wirklich sagen, was los ist.
Ich werde diesen Thread im Auge behalten, um zu sehen, ob "klügere" Leute wissen, WARUM dies geschieht.
quelle