Ein konstanter Scan dauert entweder 0 Sekunden oder 2-3 Minuten

9

Eine Abfrage wie die folgende, die garantiert keine Zeilen zurückgibt, dauert auf einem unserer Server zwischen 0 und 160 Sekunden:

select col1, col2, col3
from tab1
where 0 = 1

Vor zwei Wochen geschah dies sechsmal im Abstand von 48 Stunden. Letzte Woche dauerte die gleiche Abfrage ~ 0 Sekunden. Ich habe Protokolle der SQLs unserer Anwendung, aber noch keine Verdächtigen gefunden. Außerdem dachte ich, dass eine Abfrage vom Typ 0 / wobei 0 = 1 niemals die Datenseiten trifft, also sollte sie gegen Datensperren auf Zeilen- / Seiten- / Tabellenebene resistent sein? Das Schema wird von keinen (bekannten) SQLs berührt.

Da das Problem nicht konsistent ist und der Server sehr stark ausgelastet ist, möchte ich die Theorie hinter dem Geschehen verstehen, bevor ich den SQL-Profiler anhänge. Andere Abfragen werden während dieser Verzögerungen problemlos ausgeführt. Ein bekanntes Problem in der Anwendung ist eine hohe Anzahl dynamisch erstellter SQL-Abfragen - etwa 200.000 eindeutige Abfragen mit insgesamt 850.000 (protokollierten) Abfragen über einen Zeitraum von 48 Stunden. Kann dies zu solchen Problemen führen?

Auf dem Server wird SQL Server 2005 Standard Edition, 96 GB RAM, Festplatten im SAN und 4 CPUs / 16 Kerne ausgeführt. Datenbankdateien und Dateigruppen sind gut optimiert und sollten kein Problem darstellen (wir untersuchen dies jedoch separat).

Alle Hinweise, wo zu suchen, wird sehr geschätzt.

Edit: Perfekt! Die Abfrage wurde wiederholt, um den Ausführungsplan hinzuzufügen, und es dauerte 1 Minute und 35 Sekunden. Hier ist der Ausführungsplan und der Screenshot mit der Abfragedauer: Abfrageplan

Bearbeiten 2: Details zur Statistikzeit für einen zweiten Lauf. Scheint momentan konstant langsam zu sein, daher werden wir Profiler und Perfmon anhängen:

SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 97402 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
Ereignishorizont
quelle
Könnten Sie bitte den Ausführungsplan beifügen? STRG + M im Abfragefenster vor der Ausführung.
Craig Efrein
2
Könnte es ein Verriegelungsproblem sein? DML-Anweisungen aus anderen Sitzungen blockieren die Auswahl in der Tabelle (dies ist das Standardverhalten in SQL Server 2005)
a_horse_with_no_name
Es gibt keine bekannten DML-Anweisungen, was die einzige Ursache ist, an die ich denken kann, aber wir untersuchen dies immer noch. Der Ausführungsplan wird der Frage hinzugefügt.
EventHorizon
Nach dem, was ich gelesen habe, ist dies nur einer dieser trivialen Ausführungspläne, die MSSQL verwendet, um das Lesen von Heaps und Indizes zu vermeiden, wenn der Optimierer weiß, dass keine Zeilen zurückgegeben werden müssen
Craig Efrein
1
Ich habe einen Fall gesehen, der so aussah. Es stellte sich heraus, dass Aktualisierungsstatistiken ausgelöst wurden (die automatische Aktualisierungsstatistik wurde aktiviert und der Wartungsplan wurde beschädigt).
Joshua

Antworten:

18

Es scheint, als ob selbst mit einer ... WHERE 0 = 1Klausel weiterhin eine Absichtssperre ( IS) für die Tabelle erforderlich ist . Lassen Sie uns dies beweisen:

Ich werde zunächst eine Testtabelle erstellen:

use TestDb1;
go

create table dbo.MyTestTable1
(
    Id int identity(1, 1) not null,
    SomeInt int not null
);
go

insert into dbo.MyTestTable1 (SomeInt)
values (10), (20), (30), (40), (50);
go

Nachdem ich meine Testtabelle habe, werde ich in einer Sitzung (Abfragefenster) Folgendes ausführen, um eine exklusive ( X) Sperre zu aktivieren dbo.MyTestTable1:

use TestDb1;
go

begin tran;
    select
        Id, SomeInt
    from dbo.MyTestTable1 with (tablockx);
--commit tran;

Ich kann die exklusive Sperre anhand der sys.dm_tran_locksDMV überprüfen . Dann mache ich in einer anderen Sitzung (neues Abfragefenster) genau das, was Ihre Abfrage macht:

use TestDb1;
go

select
    Id, SomeInt
from dbo.MyTestTable1
where 0 = 1;

Auf den ersten Blick sehe ich, dass es nicht abgeschlossen ist. Beim Betrachten sys.dm_exec_requestssehe ich genau, warum dies der Fall ist:

select
    r.session_id,
    r.status,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    r.blocking_session_id
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where st.text like '%where 0 = 1%'
and r.session_id <> @@spid;

Geben Sie hier die Bildbeschreibung ein

Ich kann hier sehen, dass meine ... WHERE 0 = 1Abfrage auf eine ISSperre für dieses Objekt wartet (die object_id übersetzt in dbo.MyTestTable1).

Ich sage keineswegs, dass Parallelität Ihr Problem ist, aber durch die Geräusche zeigen Sie die Symptome. Das obige Beispiel soll beweisen, dass Sie auch mit einer WHEREKlausel, die niemals Daten zurückgibt, nicht vom Sperren und Blockieren befreit sind .

Alles, was wir tun können, ist zu raten. Wenn es also "lange dauert", müssen Sie genau sehen, was diese Anfrage tut, die so lange dauert. Wenn es auf etwas wartet, dann sehen Sie, worauf es wartet.

Thomas Stringer
quelle
1

Abhängig davon, wie stachelig und threadsicher Ihre Abfragen sind, stellt Ihr System diese Abfrage möglicherweise einfach in die Warteschlange. Die Standardanzahl der Worker (dh die Anzahl der gleichzeitigen SQL Server-Threads) für Ihr Setup sollte etwa 700 betragen.

Überprüfen Sie sys.dm_os_schedulers und sys.dm_os_waiting_tasks, um festzustellen, ob dies ein Problem sein könnte.

Sascha Rambeaud
quelle
Ein guter Vorschlag, aber das Problem war schließlich eine dumme Sperre.
Eventhorizon
Ich war nicht wirklich überzeugt, da 700 Arbeiter genug sind, aber es war leicht zu überprüfen (und somit auszuschließen)
Sascha Rambeaud