Dizin sütunundaki çok büyük bir tablodan TOP 1 SEÇ çok yavaş, ancak ters sırada değil (“desc”)


17

SQL Server 2014'ü güçlü bir sunucuda çalıştıran 1 TB'lık büyük bir veritabanımız var. Her şey birkaç yıl boyunca iyi çalıştı. Yaklaşık 2 hafta önce, aşağıdakileri içeren tam bir bakım yaptık: Tüm yazılım güncellemelerini yükleyin; tüm dizinleri ve kompakt DB dosyalarını yeniden oluşturun. Ancak, gerçek aşama aynı olduğunda DB'nin CPU kullanımının% 100'ün üzerinde% 150'ye çıkmasını beklemiyorduk.

Birçok sorun giderme işleminden sonra, bunu çok basit bir sorguya daralttık, ancak bir çözüm bulamadık. Sorgu son derece basittir:

select top 1 EventID from EventLog with (nolock) order by EventID

Her zaman yaklaşık 1,5 saniye sürer! Ancak, "desc" ile benzer bir sorgu her zaman yaklaşık 0 ms sürer:

select top 1 EventID from EventLog with (nolock) order by EventID desc

PTable'ın yaklaşık 500 milyon satırı vardır; bigint veri türüne sahip EventIDbirincil kümelenmiş dizin sütunu (sıralı ASC) (Kimlik sütunu). Üstteki tabloya veri ekleyen birden çok iş parçacığı vardır (daha büyük EventID'ler) ve alttan veri silinen 1 iş parçacığı vardır (daha küçük EventID'ler).

SMS'lerde, iki sorgunun her zaman aynı yürütme planını kullandığını doğruladık:

  • Kümelenmiş dizin taraması;

  • Tahmini ve gerçek satır numaralarının her ikisi de 1'dir;

  • Tahmini ve gerçek yürütme sayısı 1'dir;

  • Tahmini G / Ç maliyeti 8500 (Yüksek gibi görünüyor)

  • Art arda çalıştırılırsa, Sorgu maliyeti her ikisi için de aynı% 50'dir.

Dizin istatistiklerini güncelledim with fullscan, sorun devam etti; Dizini yeniden oluşturdum ve sorun yarım gün boyunca gitmiş gibi görünüyordu, ama geri döndü.

IO istatistiklerini aşağıdakilerle açtım:

set statistics io on

ardından iki sorguyu art arda çalıştırdı ve aşağıdaki bilgileri buldu:

(İlk sorgu için yavaş olan)

'PTable' tablosu. Tarama sayısı 1, mantıksal okuma 407670, fiziksel okuma 0, okuma öncesinde 0 okuma, lob mantıksal okuma 0, lob fiziksel okuma 0, lob okuma öncesinde 0 okuma.

(İkinci sorgu için hızlı olan)

'PTable' tablosu. Tarama sayısı 1, mantıksal okumalar 4, fiziksel okumalar 0, okuma öncesinde okumalar 0, lob mantıksal okumalar 0, lob fiziksel okumalar 0, lob okuma öncesinde okumalar 0.

Mantıksal okumalardaki büyük farklılığa dikkat edin. Endeks her iki durumda da kullanılır.

Endeks parçalanması biraz açıklayabilir, ancak etkinin çok küçük olduğuna inanıyorum; ve sorun daha önce hiç olmadı. Başka bir kanıt ben gibi bir sorgu çalıştırmak ise:

select * from EventLog with (nolock) where EventID=xxxx   

Xxxx'i tablodaki en küçük EventID'lere ayarlasam bile, sorgu her zaman hızlıdır.

Kontrol ettik ve kilitleme / engelleme sorunu yok.

Not: Yukarıdaki sorunu basitleştirmeye çalıştım. "PTable" aslında "EventLog" dur; PIDolduğunu EventID.

NOLOCKİpucu olmadan aynı sonuç testini alıyorum .

Birisi yardım edebilir mi?

resim açıklamasını buraya girin

resim açıklamasını buraya girin

XML'de daha ayrıntılı sorgu yürütme planları aşağıdaki gibidir:

https://www.brentozar.com/pastetheplan/?id=SJ3eiVnob

https://www.brentozar.com/pastetheplan/?id=r1rOjVhoZ

Tablo ifadesi oluşturmanın önemli olduğunu düşünmüyorum. Bu eski bir veritabanı ve bakım kadar uzun süre mükemmel çalışıyor. Kendimizi birçok araştırma yaptık ve sorumun verdiği bilgiye daralttık.

Tablo normalde EventIDsütunun birincil anahtar olan bir tür identitysütun olduğu şekilde oluşturulmuştur bigint. Şu anda, sanırım sorun dizin parçalanmasıyla ilgili. Endeksin yeniden oluşturulmasından hemen sonra, sorun yarım gün boyunca ortadan kalkmış gibi görünüyordu; ama neden bu kadar çabuk geri döndü ...?

Yanıtlar:


18

Kümelenmiş Dizin Taraması, 1926 ms sürerek ilk satırı döndürmek için 423.723 mantıksal okuma gösterir:

FINDIK

Bu, ilk satırı dizin düzeninde bulmak için çok fazla gibi görünüyor.

Büyük olasılıkla hayalet temizleme göreviniz çok geride ya da durdu. ghost_record_countKümelenmiş dizini kontrol etmeli sys.dm_db_index_physical_statsve zaman içindeki değişiklikleri izlemelisiniz.

Tarama sipariş bunun karşılığında siz 'diri' satır bulmadan hayalet kayıtların çok şey üzerinde tarama yapmak vardır sürekli silme etkinlik görmeye endeksin ucundan. Bu ekstra mantıklı okumaları açıklar. B-ağacını indeksin en düşük değerine doğru aramak, daha az hayalet kayıtla karşılaşır.

Performansı etkileyen başka bir faktör de, Paul Randal'ın Depolama Motorunun İçi: Hayalet temizlemesinde belirtildiği gibi hayalet kayıtlarını kaldırmaktan taramanın kendisinin sorumlu olmasıdır .

İzleme bayrağı 661'in (hayalet temizlemeyi devre dışı bırakma) etkin olmadığını kontrol etmelisiniz.

Çözümler

Hayalet temizleme işlemi tamamen durduysa, en etkili çözüm normalde SQL Server örneğini yeniden başlatmaktır. Ayrıca SQL Server'ın en son Toplu Güncelleştirmeler'den birini çalıştırdığından emin olmalısınız. Yıllar boyunca birçok hayalet temizleme hatası olmuştur.

Özel durumunuzda:

Sorunun aynı sunucudaki başka bir test veritabanından kaynaklandığı ortaya çıktı. Bu test veritabanı "veri kaybı" ile geri yüklendi ve bozuk. Şaşırtıcı bir şekilde, hayalet temizleme işlemi görünüşte bu veritabanında sıkışmıştı. Bu bozuk veritabanını SMSS'den sildikten sonra, sorun kendi kendine çözüldü (uzun sürdü ve DB'nin kısa bir süre kilitlenmesine neden olabilir).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.