Problemen met query's oplossen die nooit op SQL Server
In dit artikel worden de stappen voor probleemoplossing beschreven voor het probleem waarbij u een query hebt die nooit lijkt te zijn voltooid, of het voltooien ervan vele uren of dagen kan duren.
Wat is een oneindige query?
Dit document is gericht op query's die nog steeds worden uitgevoerd of gecompileerd, dat wil gezegd dat hun CPU blijft toenemen. Het is niet van toepassing op query's die zijn geblokkeerd of wachten op een resource die nooit is vrijgegeven (de CPU blijft constant of verandert heel weinig).
Belangrijk
Als een query wordt overgelaten om de uitvoering te voltooien, wordt deze uiteindelijk voltooid. Dit kan slechts enkele seconden duren, of het kan enkele dagen duren.
De term never-ending wordt gebruikt om de perceptie te beschrijven dat een query niet wordt voltooid, terwijl de query uiteindelijk wordt voltooid.
Een oneindige query identificeren
Voer de volgende stappen uit om te bepalen of een query continu wordt uitgevoerd of vastloopt op een knelpunt:
Voer de volgende query uit:
DECLARE @cntr int = 0 WHILE (@cntr < 3) BEGIN SELECT TOP 10 s.session_id, r.status, r.wait_time, r.wait_type, r.wait_resource, r.cpu_time, r.logical_reads, r.reads, r.writes, r.total_elapsed_time / (1000 * 60) 'Elaps M', SUBSTRING(st.TEXT, (r.statement_start_offset / 2) + 1, ((CASE r.statement_end_offset WHEN -1 THEN DATALENGTH(st.TEXT) ELSE r.statement_end_offset END - r.statement_start_offset) / 2) + 1) AS statement_text, COALESCE(QUOTENAME(DB_NAME(st.dbid)) + N'.' + QUOTENAME(OBJECT_SCHEMA_NAME(st.objectid, st.dbid)) + N'.' + QUOTENAME(OBJECT_NAME(st.objectid, st.dbid)), '') AS command_text, r.command, s.login_name, s.host_name, s.program_name, s.last_request_end_time, s.login_time, r.open_transaction_count, atrn.name as transaction_name, atrn.transaction_id, atrn.transaction_state FROM sys.dm_exec_sessions AS s JOIN sys.dm_exec_requests AS r ON r.session_id = s.session_id CROSS APPLY sys.Dm_exec_sql_text(r.sql_handle) AS st LEFT JOIN (sys.dm_tran_session_transactions AS stran JOIN sys.dm_tran_active_transactions AS atrn ON stran.transaction_id = atrn.transaction_id) ON stran.session_id =s.session_id WHERE r.session_id != @@SPID ORDER BY r.cpu_time DESC SET @cntr = @cntr + 1 WAITFOR DELAY '00:00:05' END
Controleer de voorbeelduitvoer.
De stappen voor probleemoplossing in dit artikel zijn specifiek van toepassing wanneer u een uitvoer ziet die vergelijkbaar is met de volgende, waarbij de CPU evenredig toeneemt met de verstreken tijd, zonder aanzienlijke wachttijden. Het is belangrijk om te weten dat wijzigingen in
logical_reads
in in dit geval niet relevant zijn, omdat sommige CPU-gebonden T-SQL-aanvragen mogelijk helemaal geen logische leesbewerkingen uitvoeren (bijvoorbeeld berekeningen of eenWHILE
lus uitvoeren).session_id Status cpu_time logical_reads wait_time wait_type 56 Met 7038 101000 0 NULL 56 uitvoerbaar 12040 301000 0 NULL 56 Met 17020 523000 0 NULL Dit artikel is niet van toepassing als u een wachtscenario ziet dat vergelijkbaar is met het volgende scenario waarbij de CPU niet of weinig verandert en de sessie wacht op een resource.
session_id Status cpu_time logical_reads wait_time wait_type 56 Geschorst 0 3 8312 LCK_M_U 56 Geschorst 0 3 13318 LCK_M_U 56 Geschorst 0 5 18331 LCK_M_U
Zie Wachttijden of knelpunten vaststellen voor meer informatie.
Lange compilatietijd
In zeldzame gevallen ziet u misschien dat de CPU in de loop van de tijd voortdurend toeneemt, maar dat dit niet wordt veroorzaakt door de uitvoering van query's. In plaats daarvan kan dit worden aangestuurd door een te lange compilatie (het parseren en compileren van een query). Controleer in dat geval de transaction_name uitvoerkolom en zoek naar een waarde van sqlsource_transform
. Deze transactienaam geeft een compilatie aan.
Diagnostische gegevens verzamelen
- SQL Server 2008 - SQL Server 2014 (vóór SP2)
- SQL Server 2014 (na SP2) en SQL Server 2016 (vóór SP1)
- SQL Server 2016 (na SP1) en SQL Server 2017
- SQL Server 2019 en nieuwere versies
Voer de volgende stappen uit om diagnostische gegevens te verzamelen met behulp van SQL Server Management Studio (SSMS):
Leg de geschatte XML van het queryuitvoeringsplan vast .
Bekijk het queryplan om te zien of er duidelijke aanwijzingen zijn van waar de traagheid vandaan kan komen. Typische voorbeelden zijn:
- Tabel- of indexscans (bekijk geschatte rijen).
- Geneste lussen die worden aangedreven door een enorme gegevensset voor buitenste tabellen.
- Geneste lussen met een grote tak in de binnenkant van de lus.
- Tabelspools.
- Functies in de
SELECT
lijst die lang duren voordat elke rij is verwerkt.
Als de query op elk gewenst moment snel wordt uitgevoerd, kunt u de 'snelle' uitvoeringen vastleggen Werkelijke XML-uitvoeringsplan om te vergelijken.
Methode voor het controleren van de verzamelde plannen
In deze sectie wordt uitgelegd hoe u de verzamelde gegevens kunt controleren. Er worden meerdere XML-queryplannen (met extensie *.sqlplan) gebruikt die zijn verzameld in SQL Server 2016 SP1 en latere builds en versies.
Volg deze stappen om uitvoeringsplannen te vergelijken:
Open een eerder opgeslagen bestand met een queryuitvoeringsplan (.sqlplan).
Klik met de rechtermuisknop in een leeg gebied van het uitvoeringsplan en selecteer Showplan vergelijken.
Kies het tweede queryplanbestand dat u wilt vergelijken.
Zoek naar dikke pijlen die een groot aantal rijen tussen operatoren aangeven. Selecteer vervolgens de operator vóór of na de pijl en vergelijk het aantal werkelijke rijen tussen twee plannen.
Vergelijk het tweede en derde plan om te zien of de grootste stroom rijen plaatsvindt in dezelfde operatoren.
Hier volgt een voorbeeld:
Oplossing
Zorg ervoor dat de statistieken zijn bijgewerkt voor de tabellen die in de query worden gebruikt.
Zoek naar een ontbrekende indexaan aanbeveling in het queryplan en pas een van de aanbevelingen toe.
Herschrijf de query met als doel deze te vereenvoudigen:
- Gebruik meer selectieve
WHERE
predicaten om de vooraf verwerkte gegevens te verminderen. - Breek het uit elkaar.
- Selecteer enkele onderdelen in tijdelijke tabellen en voeg ze later samen.
- Verwijder
TOP
,EXISTS
enFAST
(T-SQL) in de query's die zeer lang worden uitgevoerd vanwege een optimalisatierijdoel. U kunt ook deDISABLE_OPTIMIZER_ROWGOAL
hint gebruiken. Zie Row Goals Gone Rogue voor meer informatie. - Vermijd het gebruik van Common Table Expressions (CTE's) in dergelijke gevallen, omdat ze instructies combineren tot één grote query.
- Gebruik meer selectieve
Probeer queryhints te gebruiken om een beter plan te maken:
HASH JOIN
ofMERGE JOIN
hintFORCE ORDER
HintFORCESEEK
HintRECOMPILE
- GEBRUIK
PLAN N'<xml_plan>'
als u een snel queryplan hebt dat u kunt afdwingen
Gebruik Query Store (QDS) om een bekend plan af te dwingen als een dergelijk plan bestaat en als uw SQL Server versie Query Store ondersteunt.
Wachttijden of knelpunten vaststellen
Deze sectie is hier opgenomen als een referentie voor het geval uw probleem geen langlopende CPU-aansturende query is. U kunt het gebruiken om problemen met query's op te lossen die lang zijn vanwege wachttijden.
Als u een query wilt optimaliseren die wacht op knelpunten, identificeert u hoe lang de wachttijd is en waar het knelpunt zich bevindt (het wachttype). Zodra het wachttype is bevestigd, vermindert u de wachttijd of elimineert u de wachttijd volledig.
Als u de geschatte wachttijd wilt berekenen, trekt u de CPU-tijd (werktijd) af van de verstreken tijd van een query. Normaal gesproken is de CPU-tijd de werkelijke uitvoeringstijd en wacht het resterende deel van de levensduur van de query.
Voorbeelden van het berekenen van de geschatte wachttijd:
Verstreken tijd (ms) | CPU-tijd (ms) | Wachttijd (ms) |
---|---|---|
3200 | 3000 | 200 |
7080 | 1000 | 6080 |
Het knelpunt identificeren of wachten
Voer de volgende query uit om historische langverwachte query's te identificeren (bijvoorbeeld >20% van de totale verstreken tijd is wachttijd). Deze query maakt gebruik van prestatiestatistieken voor queryplannen in de cache sinds het begin van SQL Server.
SELECT t.text, qs.total_elapsed_time / qs.execution_count AS avg_elapsed_time, qs.total_worker_time / qs.execution_count AS avg_cpu_time, (qs.total_elapsed_time - qs.total_worker_time) / qs.execution_count AS avg_wait_time, qs.total_logical_reads / qs.execution_count AS avg_logical_reads, qs.total_logical_writes / qs.execution_count AS avg_writes, qs.total_elapsed_time AS cumulative_elapsed_time FROM sys.dm_exec_query_stats qs CROSS apply sys.Dm_exec_sql_text (sql_handle) t WHERE (qs.total_elapsed_time - qs.total_worker_time) / qs.total_elapsed_time > 0.2 ORDER BY qs.total_elapsed_time / qs.execution_count DESC
Voer de volgende query uit om te bepalen welke query's momenteel worden uitgevoerd met wachttijden die langer zijn dan 500 ms:
SELECT r.session_id, r.wait_type, r.wait_time AS wait_time_ms FROM sys.dm_exec_requests r JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id WHERE wait_time > 500 AND is_user_process = 1
Als u een queryplan kunt verzamelen, controleert u de WaitStats van de eigenschappen van het uitvoeringsplan in SSMS:
- Voer de query uit met Werkelijke uitvoeringsplan opnemen op.
- Klik met de rechtermuisknop op de operator die het meest links is op het tabblad Uitvoeringsplan
- Selecteer Eigenschappen en vervolgens de eigenschap WaitStats .
- Controleer de WaitTimeMs en WaitType.
Als u bekend bent met PSSDiag/SQLdiag- of SQL LogScout LightPerf/GeneralPerf-scenario's, kunt u een van deze scenario's gebruiken om prestatiestatistieken te verzamelen en wachtende query's op uw SQL Server exemplaar te identificeren. U kunt de verzamelde gegevensbestanden importeren en de prestatiegegevens analyseren met SQL Nexus.
Verwijzingen om wachttijden te voorkomen of te verminderen
De oorzaken en oplossingen voor elk wachttype variëren. Er is geen enkele algemene methode om alle wachttypen op te lossen. Hier volgen artikelen om veelvoorkomende problemen met wachttypen op te lossen:
- Blokkeringsproblemen begrijpen en oplossen (LCK_M_*)
- Problemen met Azure SQL databaseblokkering begrijpen en oplossen
- Trage SQL Server prestaties oplossen die worden veroorzaakt door I/O-problemen (PAGEIOLATCH_*, WRITELOG, IO_COMPLETION, BACKUPIO)
- Conflict met laatste pagina invoegen PAGELATCH_EX in SQL Server oplossen
- Geheugen verleent uitleg en oplossingen (RESOURCE_SEMAPHORE)
- Problemen met trage query's oplossen die het gevolg zijn van ASYNC_NETWORK_IO wachttype
- Problemen met een hoog HADR_SYNC_COMMIT-wachttype oplossen met AlwaysOn-beschikbaarheidsgroepen
- Hoe het werkt: CMEMTHREAD en foutopsporing
- Parallelle wachttijden uitvoeren (CXPACKET en CXCONSUMER)
- THREADPOOL-wachttijd
Zie de tabel in Typen wachttijden voor beschrijvingen van veel wachttypen en wat ze aangeven.
Feedback
https://aka.ms/ContentUserFeedback.
Binnenkort beschikbaar: In de loop van 2024 zullen we GitHub-problemen geleidelijk uitfaseren als het feedbackmechanisme voor inhoud en deze vervangen door een nieuw feedbacksysteem. Zie voor meer informatie:Feedback verzenden en weergeven voor