Aracılığıyla paylaş


SQL Server hiç bitmemiş gibi görünen sorgularda sorun giderme

Bu makalede, hiçbir zaman tamamlanmamış gibi görünen bir sorgunuz olduğu veya tamamlanmasının birkaç saat veya gün sürebileceği sorun için sorun giderme adımları açıklanmaktadır.

Hiç bitmeyen sorgu nedir?

Bu belge, yürütmeye veya derlemeye devam eden sorgulara, yani CPU'larının artmaya devam etmesine odaklanır. Engellenen veya hiçbir zaman yayımlanmayan bir kaynağı bekleyen sorgular için geçerli değildir (CPU sabit kalır veya çok az değişir).

Önemli

Yürütmeyi tamamlamak için bir sorgu bırakılırsa, sonunda tamamlanır. Yalnızca birkaç saniye veya birkaç gün sürebilir.

Hiçbir zaman bitmeyen terim, sorgu sonunda tamamlandığında sorgunun tamamlanmadığı algısını açıklamak için kullanılır.

Hiç bitmeyen bir sorguyu tanımlama

Sorguların sürekli olarak yürütülüyor mu yoksa bir performans sorununa mı takılı kaldığını belirlemek için şu adımları izleyin:

  1. Aşağıdaki sorguyu çalıştırın:

    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
    
  2. Örnek çıkışı denetleyin.

    • Bu makaledeki sorun giderme adımları, cpu'nun geçen süreyle orantılı olarak önemli bekleme süreleri olmadan arttığı aşağıdakine benzer bir çıkış fark ettiğinizde özellikle geçerlidir. Bazı CPU'ya bağlı T-SQL istekleri hiç mantıksal okuma yapmayabileceği için (örneğin hesaplamalar veya WHILE döngü gerçekleştirme) içindeki değişikliklerin logical_reads bu durumda uygun olmadığını unutmayın.

      Session_id Durum cpu_time logical_reads wait_time wait_type
      56 Çalışan 7038 101000 0 NULL
      56 çalıştırılabilir 12040 301000 0 NULL
      56 Çalışan 17020 523000 0 NULL
    • Cpu'nun çok az değişmediği veya çok az değişmediği ve oturumun bir kaynakta beklediği aşağıdakine benzer bir bekleme senaryosu gözlemlerseniz bu makale geçerli değildir.

      Session_id Durum cpu_time logical_reads wait_time wait_type
      56 Askıya 0 3 8312 LCK_M_U
      56 Askıya 0 3 13318 LCK_M_U
      56 Askıya 0 5 18331 LCK_M_U

    Daha fazla bilgi için bkz. Beklemeleri veya performans sorunlarını tanılama.

Uzun derleme süresi

Nadir durumlarda CPU'nun zaman içinde sürekli arttığını ancak bunun sorgu yürütme tarafından yönlendirilmediğini gözlemleyebilirsiniz. Bunun yerine, aşırı uzun bir derleme (sorguyu ayrıştırma ve derleme) tarafından yönlendirilebilir. Bu gibi durumlarda , transaction_name çıkış sütununu denetleyin ve değerini sqlsource_transformarayın. Bu işlem adı bir derlemeyi gösterir.

Tanılama verilerini toplama

SQL Server Management Studio (SSMS) kullanarak tanılama verilerini toplamak için şu adımları izleyin:

  1. Tahmini sorgu yürütme planı XML'sini yakalayın.

  2. Yavaşlığın nereden gelebileceğine dair belirgin göstergeler olup olmadığını görmek için sorgu planını gözden geçirin. Tipik örnekler şunlardır:

    • Tablo veya dizin taramaları (tahmini satırlara bakın).
    • Büyük bir dış tablo veri kümesi tarafından yönlendirilen iç içe döngüler.
    • Döngünün iç tarafında büyük bir dal bulunan iç içe döngüler.
    • Tablo biriktiricileri.
    • SELECT Listedeki her satırın işlenmesi uzun süren işlevler.
  3. Sorgu herhangi bir zamanda hızlı çalışıyorsa, karşılaştırmak için "hızlı" yürütmeleri Gerçek XML Yürütme Planı'nı yakalayabilirsiniz.

Toplanan planları gözden geçirme yöntemi

Bu bölümde toplanan verilerin nasıl gözden geçirileceği gösterilmektedir. SQL Server 2016 SP1 ve sonraki derlemelerde ve sürümlerde toplanan birden çok XML sorgu planını (*.sqlplan uzantısını kullanarak) kullanır.

Yürütme planlarını karşılaştırmak için şu adımları izleyin:

  1. Daha önce kaydedilmiş bir sorgu yürütme planı dosyasını (.sqlplan) açın.

  2. Yürütme planının boş bir alanına sağ tıklayın ve Showplan'ı Karşılaştır'ı seçin.

  3. Karşılaştırmak istediğiniz ikinci sorgu planı dosyasını seçin.

  4. İşleçler arasında akan çok sayıda satırı gösteren kalın okları arayın. Ardından, ok öncesinde veya sonrasında işleci seçin ve iki plandaki gerçek satır sayısını karşılaştırın.

  5. En büyük satır akışının aynı işleçlerde olup olmadığını görmek için ikinci ve üçüncü planları karşılaştırın.

    İşte bir örnek:

    SSMS'de sorgu planlarını karşılaştırın.

Çözüm

  1. Sorguda kullanılan tablolar için istatistiklerin güncelleştirildiğinden emin olun.

  2. Sorgu planında eksik bir dizin önerisi arayın ve herhangi birini uygulayın.

  3. Sorguyu basitleştirmek amacıyla yeniden yazın:

    • Önceden işlenen verileri azaltmak için daha fazla seçmeli WHERE koşul kullanın.
    • Parçala.
    • Geçici tablolarda bazı bölümleri seçin ve daha sonra birleştirin.
    • İyileştirici satır hedefi nedeniyle çok uzun süre çalışan sorgularda , EXISTSve FAST (T-SQL) öğelerini kaldırınTOP. Alternatif olarak ipucunuDISABLE_OPTIMIZER_ROWGOAL kullanabilirsiniz. Daha fazla bilgi için bkz. Satır Goals Gone Rogue.
    • Deyimleri tek bir büyük sorguda birleştirdikleri durumlarda Ortak Tablo İfadeleri (CTE) kullanmaktan kaçının.
  4. Daha iyi bir plan oluşturmak için sorgu ipuçlarını kullanmayı deneyin:

    • HASH JOIN veya MERGE JOIN ipucu
    • FORCE ORDER Ipucu
    • FORCESEEK Ipucu
    • RECOMPILE
    • Zorlayabileceğiniz hızlı bir sorgu planınız varsa KULLAN PLAN N'<xml_plan>'
  5. Böyle bir plan varsa ve SQL Server sürümünüz Sorgu Deposu'yu destekliyorsa, iyi bilinen bir planı zorlamak için Sorgu Deposu'yu (QDS) kullanın.

Beklemeleri veya performans sorunlarını tanılama

Bu bölüm, sorununuzun uzun süre çalışan bir CPU sürüş sorgusu olmadığı durumlarda başvuru olarak buraya eklenmiştir. Bekleme süresi uzun olan sorgularla ilgili sorunları gidermek için bunu kullanabilirsiniz.

Performans sorunlarını bekleyen bir sorguyu iyileştirmek için, beklemenin ne kadar sürdüğünü ve performans sorununun nerede olduğunu (bekleme türü) belirleyin. Bekleme türü onaylandıktan sonra bekleme süresini azaltın veya beklemeyi tamamen ortadan kaldırın.

Yaklaşık bekleme süresini hesaplamak için, sorgunun geçen zamanından CPU süresini (çalışan saati) çıkarın. Genellikle CPU süresi gerçek yürütme süresidir ve sorgunun ömrünün kalan bölümü bekler.

Yaklaşık bekleme süresini hesaplama örnekleri:

Geçen Süre (ms) CPU Süresi (ms) Bekleme süresi (ms)
3200 3000 200
7080 1000 6080

Performans sorununu belirleme veya bekleme

  • Geçmiş uzun süre bekleyen sorguları (örneğin, >geçen sürenin %20'sini bekleme süresi) tanımlamak için aşağıdaki sorguyu çalıştırın. Bu sorgu, SQL Server başlangıcından bu yana önbelleğe alınmış sorgu planları için performans istatistiklerini kullanır.

    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
    
  • Şu anda 500 ms'den uzun bekleme süreleriyle yürütülen sorguları belirlemek için aşağıdaki sorguyu çalıştırın:

    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
    
  • Sorgu planı toplayabilirseniz SSMS'deki yürütme planı özelliklerindenWaitStats'ı denetleyin:

    1. Sorguyu Fiili Yürütme Planını Ekle açık olarak çalıştırın.
    2. Yürütme planı sekmesinde en soldaki işleci sağ tıklatın
    3. Özellikler'i ve ardından WaitStats özelliğini seçin.
    4. WaitTimeMs ve WaitType değerlerini denetleyin.
  • PSSDiag/SQLdiag veya SQL LogScout LightPerf/GeneralPerf senaryolarını biliyorsanız, performans istatistiklerini toplamak ve SQL Server örneğinizde bekleyen sorguları belirlemek için bunlardan birini kullanmayı göz önünde bulundurun. Toplanan veri dosyalarını içeri aktarabilir ve SQL Nexus ile performans verilerini analiz edebilirsiniz.

Beklemeleri ortadan kaldırmaya veya azaltmaya yardımcı olacak başvurular

Her bekleme türünün nedenleri ve çözümleri farklılık gösterir. Tüm bekleme türlerini çözümlemek için tek bir genel yöntem yoktur. Sık karşılaşılan bekleme türü sorunlarını gidermeye ve çözmeye yönelik makaleler şunlardır:

Birçok Bekleme türünün açıklamaları ve bunların ne gösterdiği için Bekleme Türleri'ndeki tabloya bakın.