Doktoru bu bölümlenmiş görünümde alakasız tabloları ortadan kaldırmaya zorlamak mümkün mü?


22

Büyük masalar için farklı mimarileri test ediyorum ve gördüğüm bir öneri, bölünmüş bir görünüm kullanmak, bu yüzden de büyük bir tablonun daha küçük, "bölümlenmiş" tablolara bölünmesi.

1 , 2 , 3 , 4

Bu yaklaşımı test ederken, bana anlamlı gelmeyen bir şey keşfettim. Durum görünümünde "bölümleme sütunu" nu filtrelediğimde, optimizer yalnızca ilgili tabloları arar. Ek olarak, boyut tablosundaki bu sütunu filtrelersem, optimize edici gereksiz tabloları ortadan kaldırır.

Bununla birlikte, boyutun başka bir yönüne filtre uygularsam, optimize edici her temel tablonun PK / CI'sini arar.

İşte söz konusu sorular:

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where o.ObservationDateKey >= 20000101
    and o.ObservationDateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.DateKey >= 20000101
    and od.DateKey <= 20051231
group by od.[Year];

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where od.[Year] >= 2000 and od.[Year] < 2006
group by od.[Year];

anahtar üzerindeki gerçek filtre

anahtar üzerindeki loş filtre

görünüşe göre dim filtresi

İşte SQL Sentry Plan Explorer oturumu için bir link .

Aslında benzer bir şekilde yanıt vermek için bölüm atma alıp almadığımı görmek için daha büyük olan tabloyu bölümlere ayırmaya çalışıyorum.

Boyutun bir yönünü filtreleyen (basit) sorgu için bölüm ortadan kaldırması alıyorum.

Bu arada, işte veritabanının sadece istatistik bir kopyası:

https://gist.github.com/swasheck/9a22bf8a580995d3b2aa

"Eski" kardinalite tahmincisi daha az pahalı bir plan alır, ancak bunun nedeni, (gereksiz) endeks aramalarının her biri için düşük kardinalite tahminleridir.

Optimize edicinin, boyutun başka bir özelliğine göre filtrelemede anahtar sütunu kullanmasını sağlamanın bir yolu olup olmadığını bilmek istiyorum, böylece alakasız tablolarda aramaları ortadan kaldırabilir.

SQL Server Sürümü:

Microsoft SQL Server 2014 - 12.0.2000.8 (X64) 
    Feb 20 2014 20:04:26 
    Copyright (c) Microsoft Corporation
    Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)

Sadece bir FYI .. son istatistik akışı bozulduCREATE STATISTICS [_WA_Sys_00000008_2FCF1A8A] ON [dbo].[Observation_2010]([StationStateCode]) WITH STATS_STREAM = 0x01000000010000000000000000000000D4531EDB00000000D5080000000000009508000000000000AF030000AF000000020000000000000008D000340000000007000000E65DE0007DA5000076F9780000000000867704000000000000000000ABAAAA3C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Kin Shah

Sadece istatistik veritabanı betiği kesilmiş gibi görünüyor. "Tam dosyayı görüntüle" yi tıklayıp zip'i indirmeyi denedim, ancak her iki şekilde de ObservationDatesmasa için istatistik alamadım. Paul ile aynı planı alamıyorum, 4199'da bile ve bu yüzden böyle düşünüyorum.
Geoff Patterson

@GeoffPatterson benim için çalışıyor. ham dosyanın bağlantısını tıkladınız mı? gist.githubusercontent.com/swasheck/9a22bf8a580995d3b2aa/raw/… ancak Kin'in belirttiği gibi, son istatistikler akışı bozulmuş: /
swasheck

Ham dosyanın bağlantısını tıkladım. Betik çalışıyor (Kin'in kaydettiği sorun hariç), ancak istatistik oluşturmak için herhangi bir mantık içermiyor ObservationDates. UPDATE STATISTICS ObservationDates WITH ROWCOUNT = 10000Paul'un gösterdiği planı almak için el ile koşmaya başladım .
Geoff Patterson

Garip. yeni bir veritabanı oluşturmak ve bu betiği çalıştırmak için istatistik nesnelerim var ( ObservationDatesyani , dizinler) bu yüzden neler olup bittiğinden emin değilim. Ayrıca, Paul'ün planını da yapamıyorum. görmek için güncellemeyi deneyeceğim.
swireck

Yanıtlar:


10

Izleme bayrağı 4199'u etkinleştir.

Ayrıca şunu da söylemek zorunda kaldım:

UPDATE STATISTICS dbo.ObservationDates 
WITH ROWCOUNT = 73049;

aşağıda gösterilen planları almak için. Bu tablo için istatistikler yükleme sırasında eksikti. 73,049 rakamı, Plan Explorer ekindeki Tablo Kardinalliği bilgisinden geldi. İki mantıksal işlemciyle, 2048 MB'a ayarlanmış maksimum bellekle ve 4199'dan itibaren hiçbir izleme bayrağıyla SQL Server 2014 SP1 CU4 (derleme 12.0.4436) kullandım.

Daha sonra, dinamik bölüm eliminasyonunu içeren bir yürütme planı almalısınız:

select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
where 
    od.[Year] >= 2000 and od.[Year] < 2006
group by 
    od.[Year]
option (querytraceon 4199);

Plan parçası:

Parçayı planla

Bu daha kötü görünebilir, ancak Filtrelerin hepsi başlangıç filtresidir. Örnek bir tahmin:

Filtre özellikleri

Döngünün yinelemesi başına, başlangıç ​​yüklemi test edilir ve yalnızca doğru olduğunda döndürür, altında yürütülen Kümelenmiş Dizin Araması olur. Bu nedenle, dinamik bölüm ortadan kaldırılması.

Bu belki de değil oldukça planı paralel, özellikle statik eliminasyon kadar etkili.

Sen gibi ipuçlarını denemeniz gerekebilir MAXDOP 1, FAST 1ya da FORCESEEKgörünüm üzerinde aynı planı olsun. Bölümlenmiş görünümlerle (bölümlenmiş tablolar gibi) optimize edici maliyetlendirme seçenekleri zor olabilir.

Önemli olan, bölümlenmiş görünümlerle dinamik bölüm atmayı elde etmek için başlangıç ​​filtreleri içeren bir plana ihtiyacınız var.


Gömülü USE PLANipuçlarıyla sorgular : (gist.github.com aracılığıyla):


1
Harika bilgi, teşekkürler Paul! Yanıtımı yazdıktan sonra neden SQL Server'ın bu tür bir eleme işlemi yapabileceğinin bir yolu olmadığını merak ediyordum. Öyle görünüyor ki, daha önce görmedim!
Geoff Patterson,

6

Benim gözlemim, her zaman bölümleme görünümünde "tablo eleme" almak için sorguda açıkça bölümleme sütununun değerini (veya değer aralığını) belirlemeniz gerektiği olmuştur. Bu, SQL Server 2000'den SQL Server 2014'e kadar üretimde bölümlenmiş görünümleri kullanma deneyimine dayanır.

SQL Server, motorun, döngünün dış tarafındaki sıranın değerini temel alarak döngünün iç tarafındaki uygun tabloyu doğrudan dinamik olarak aramaya yöneltebileceği bir döngü birleştirme işleci kavramına sahip değildir. Bununla birlikte, Paul'un cevabının açıkladığı gibi , başlangıçta filtreleri olan bir programın, döngünün iç tarafındaki alakasız tabloları sabit bir zamanda (gerçekten arama işlemini gerçekleştirerek logaritmik olarak) dinamik olarak atlamak için bir plan olasılığı vardır.

Bununla birlikte, bölümlenmiş tablolar için bu tür bir arama (belirli bir bölüme) desteklendiğini unutmayın.

Bölümlenmiş görünümler kullanmaya karar veriyorsanız, başka bir seçenek de sorgunuzu aşağıdakiler gibi birden çok sorguya bölmektir:

-- Gather than the min/max values for the partition column
DECLARE @minDateKey INT,
        @maxDateKey INT
SELECT @minDateKey = MIN(DateKey),
        @maxDateKey = MAX(DateKey)
FROM dbo.ObservationDates od
WHERE od.[Year] >= 2000 and od.[Year] < 2006

-- Since I have a stats-only copy of the database, simulate having run the query above
-- (You can comment this out since you have the actual data.)
SELECT @minDateKey = 20000101, @maxDateKey = 20051231

-- Adjust the query to use the min/max values of the partition column
-- rather than filtering on a different column in the dimension table
select 
    od.[Year], 
    AvgValue = avg(ObservationValue)
from dbo.v_Observation o 
join dbo.ObservationDates od
    on o.ObservationDateKey = od.DateKey
WHERE od.DateKey >= @minDateKey AND od.DateKey <= @maxDateKey
group by od.[Year]
-- Must use OPTION RECOMPILE; otherwise the plan will touch all tables because it
-- must do so in order to be valid for all values of the parameters!
OPTION (RECOMPILE)

Bu, aşağıdaki planı verir. Artık boyut tablosuna çarpan fazladan bir sorgu var, ancak (büyük olasılıkla çok daha büyük) olgu tablosundaki sorgu optimize edildi.

görüntü tanımını buraya girin


Eğer birinci sorguyu ikinciye değişkenlere başvurmadan eklerseniz aynı etki elde edilebilir mi?
Andriy M,

@AndriyM Sizi doğru anlıyorsam, cevap hayır, aynı etki elde edilemeyecek ve iki sorguyu birleştirmeyi denerseniz sorgu planı bölümlenmiş görünümdeki tüm tablolara dokunacaktır. İlk sorguyu çalıştırmanız gerekiyorsa, değerleri yapıştırın 20000101ve 20051231değişkenler yerine (veya uygulamanızdaki iki ayrı sorgu aracılığıyla benzer bir şey yapın), ardından evet, aynı etki değişkenleri kullanmadan da elde edilir.
Geoff Patterson,
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.