2,135,044,521 satırlık tabloda dizini en iyileştirme


10

Büyük bir tablo ile bir G / Ç sorunum var.

Genel istatistikler

Tablo aşağıdaki ana özelliklere sahiptir:

  • çevre: Azure SQL Veritabanı (katman P4 Premium (500 DTU))
  • satırlar: 2,135,044,521
  • 1.275 bölümler kullanılmış
  • kümelenmiş ve bölümlenmiş dizin

model

Bu tablo uygulamasıdır:

CREATE TABLE [data].[DemoUnitData](
    [UnitID] [bigint] NOT NULL,
    [Timestamp] [datetime] NOT NULL,
    [Value1] [decimal](18, 2) NULL,
    [Value2] [decimal](18, 2) NULL,
    [Value3] [decimal](18, 2) NULL,
    CONSTRAINT [PK_DemoUnitData] PRIMARY KEY CLUSTERED 
    (
        [UnitID] ASC,
        [Timestamp] ASC
    )
)
GO

ALTER TABLE [data].[DemoUnitData] WITH NOCHECK ADD CONSTRAINT [FK_DemoUnitData_Unit] FOREIGN KEY([UnitID])
REFERENCES [model].[Unit] ([ID])
GO

ALTER TABLE [data].[DemoUnitData] CHECK CONSTRAINT [FK_DemoUnitData_Unit]
GO

Bölümleme bununla ilgilidir:

CREATE PARTITION SCHEME [DailyPartitionSchema] AS PARTITION [DailyPartitionFunction] ALL TO ([PRIMARY])

CREATE PARTITION FUNCTION [DailyPartitionFunction] (datetime) AS RANGE RIGHT
FOR VALUES (N'2017-07-25T00:00:00.000', N'2017-07-26T00:00:00.000', N'2017-07-27T00:00:00.000', ... )

Hizmet kalitesi

Sanırım endeksler ve istatistikler her gece artımlı yeniden oluşturma / yeniden düzenleme / güncelleme ile korunur.

Bunlar, en yoğun kullanılan dizin bölümlerinin geçerli dizin istatistikleridir:

Bölüm İstatistikleri

Bunlar en çok kullanılan bölümlerin güncel istatistik özellikleridir:

İstatistik

Sorun

Tablo karşı yüksek bir frekans üzerinde basit bir sorgu çalıştırın.

SELECT [UnitID]
    ,[Timestamp]
    ,[Value1]
    ,[Value2]
    ,[Value3]
FROM [data].[DemoUnitData]
WHERE [UnitID] = 8877 AND [Timestamp] >= '2018-03-01' AND [Timestamp] < '2018-03-13'
OPTION (MAXDOP 1)

aşma sayısı

Yürütme planı şuna benzer: https://www.brentozar.com/pastetheplan/?id=rJvI_4TtG

Benim sorunum, bu sorgular son derece yüksek miktarda I / O işlemleri üretmek PAGEIOLATCH_SHbekler darboğaz ile sonuçlanır .

en iyi bekler

Soru

PAGEIOLATCH_SHBeklemelerin genellikle iyi optimize edilmemiş dizinlerle ilişkili olduğunu okudum . G / Ç işlemlerini nasıl azaltabileceğime dair önerileriniz var mı? Belki daha iyi bir dizin ekleyerek?


Cevap 1 - @ S4V1N'den gelen yorumla ilgili

Gönderilen sorgu planı SSMS'de yürüttüğüm bir sorgudan alındı. Yorumunuzdan sonra sunucu geçmişi hakkında biraz araştırma yapıyorum. Hizmetten istisnalı sorgu biraz farklı görünüyor (EntityFramework ile ilgili).

(@p__linq__0 bigint,@p__linq__1 datetime2(7),@p__linq__2 datetime2(7)) 

SELECT 1 AS [C1], [Extent1] 
   .[Timestamp] AS [Timestamp], [Extent1] 
   .[Value1] AS [Value1], [Extent1] 
   .[Value2] AS [Value2], [Extent1] 
   .[Value3] AS [Value3]  
FROM [data].[DemoUnitData] AS [Extent1]  
WHERE ([Extent1].[UnitID] = @p__linq__0)  
AND ([Extent1].[Timestamp] >= @p__linq__1)  
AND ([Extent1].[Timestamp] < @p__linq__2) OPTION (MAXDOP 1) 

Ayrıca, plan farklı görünüyor:

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

veya

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

Burada da görebileceğiniz gibi, DB performansımız bu sorgudan pek etkilenmiyor.

En İyi SQL

Cevap 2 - @Joe Obbish'in cevabı ile ilgili

Çözümü test etmek için Entity Framework'ü basit bir SqlCommand ile değiştirdim. Sonuç inanılmaz bir performans artışı oldu!

Sorgu planı şimdi SSMS ile aynıdır ve mantıksal okuma ve yazma işlemleri yürütme başına ~ 8'e düşer.

Toplam I / O yükü neredeyse 0'a düşüyor! I / O düşüşü

Ayrıca, bölüm aralığını aylıktan günlük olarak değiştirdikten sonra neden büyük bir performans düşüşü aldığımı da açıklıyor. Bölüm ortadan kaldırılması daha fazla bölümün taranmasına neden oldu.


2
Yürütme planına bakıldığında, bu sorgu hiç sorunlu görünmüyor. Sadece düşük okuma değeri olan gerekli bölümleri taradı ve bunun yerine pageiolatch_sh beklediğini (sos_sched ..) bildirmedi. Bu anlaşılabilir bir durum çünkü zaten fiziksel okumalarınız yoktu. Bu kümülatif beklemeler mi yoksa belirli bir süre için mi alınıyor? Belki de sorun başka bir sorgu.
S4V1N

Yukarıda @ S4V1N'de detaylı bir cevap gönderdim
Steffen Mangold

Yanıtlar:


7

PAGEIOLATCH_SHORM tarafından oluşturulan veri türlerini değiştirebiliyorsanız bu sorgu beklemelerini azaltabilirsiniz . TimestampTablonuzdaki sütun veri türü vardır DATETIMEama parametreler @p__linq__1ve @p__linq__2veri türleri vardır DATETIME2(7). Bu fark, ORM sorguları için sorgu planının, kodlanmış arama filtreleri içeren ilk sorgu planından çok daha karmaşık olmasının nedenidir. XML'de bununla ilgili bir ipucu da alabilirsiniz:

<ScalarOperator ScalarString="GetRangeWithMismatchedTypes([@p__linq__1],NULL,(22))">

Olduğu gibi, ORM sorgusu ile herhangi bir bölüm eliminasyonu alamazsınız. Yalnızca bir günlük veri arıyorsanız bile, bölüm işlevinde tanımlanan her bölüm için en az birkaç mantıksal okuma elde edersiniz. Her bölüm içinde bir dizin araması alırsınız, böylece SQL Server'ın bir sonraki bölüme geçmesi uzun sürmez, ancak belki de tüm IO eklenir.

Emin olmak için basit bir reprodüksiyon yaptım. Bölümleme işlevi içinde tanımlı 11 bölüm vardır. Bu sorgu için:

DECLARE @p__linq__0 bigint = 2000;
DECLARE @p__linq__1 datetime2(7) = '20180103';
DECLARE @p__linq__2 datetime2(7) = '20180104';

SELECT 1 AS [C1]
, [Extent1].[Timestamp] AS [Timestamp]
, [Extent1].[Value1] AS [Value1]
FROM [DemoUnitData] AS [Extent1]  
WHERE ([Extent1].[UnitID] = @p__linq__0)  
AND ([Extent1].[Timestamp] >= @p__linq__1)  
AND ([Extent1].[Timestamp] < @p__linq__2)
OPTION (MAXDOP 1) ;

IO şöyle görünüyor:

'DemoUnitData' tablosu. Tarama sayısı 11, mantıksal okumalar 40

Veri türlerini düzelttiğimde:

DECLARE @p__linq__0 bigint = 2000;
DECLARE @p__linq__1 datetime = '20180103';
DECLARE @p__linq__2 datetime = '20180104';

SELECT 1 AS [C1]
, [Extent1].[Timestamp] AS [Timestamp]
, [Extent1].[Value1] AS [Value1]
FROM [DemoUnitData] AS [Extent1]  
WHERE ([Extent1].[UnitID] = @p__linq__0)  
AND ([Extent1].[Timestamp] >= @p__linq__1)  
AND ([Extent1].[Timestamp] < @p__linq__2)
OPTION (MAXDOP 1) ;

Bölüm eliminasyonu sonucunda GÇ azalır:

'DemoUnitData' tablosu. Tarama sayısı 2, mantıksal okuma 8

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.