Dizinleri filtrelenmiş (boş olmayan değer) dizinlerle değiştirmenin etkisi nedir?


10

Projemiz çok büyük, çok karmaşık bir veritabanı yürütüyor. Yaklaşık bir ay önce, null değerleri içeren dizinlenmiş sütunlar tarafından kullanılan alanın çok fazla büyüdüğünü fark ettik. Buna bir yanıt olarak, null değerlerin% 1'inden fazlasını içeren tüm tek sütunlu dizinler arasında dinamik olarak arama yapacak komut dosyası olarak yazdım, daha sonra değerin NULL OLMAMASI koşulunda bu dizinleri filtrelenmiş dizinler olarak bırakın ve yeniden oluşturun. Bu, veritabanı boyunca yüzlerce dizini bırakır ve yeniden oluşturur ve genellikle tüm DB tarafından kullanılan alanın neredeyse% 15'ini boşaltır.

Şimdi bununla ilgili iki sorum var:

C) Filtrelenmiş dizinleri bu şekilde kullanmanın olumsuz yanları nelerdir? Yalnızca performansı artıracağını varsayıyorum, ancak performans riskleri var mı?

B) Daha sonra kontrol edildiğinde bile, her şey tam olarak beklendiği gibi gitmiş olsa bile, dizinleri bırakma ve yeniden oluşturma konusunda hatalar aldık ( 'XYZ indeksini bırakamıyorum ya da izniniz yok' ) aldık . Bu nasıl olabilir?

Herhangi bir yardım için teşekkürler!

Edit: @Thomas Kejser adlı kişiye yanıt olarak

Merhaba ve teşekkürler, ama bu bir felaket oldu. O zaman aşağıdaki gibi bazı şeyleri anlamadık:

  1. Bir sorgu sırasında SQLOS, tablo sütunlarına katılmak için NULL değerleri kullanamayacağını belirlemeden önce dizin planları yapar. IE, gerçekten sorguda kullanılan filtrelenmiş her dizin için dizin uyan bir WHERE yan tümcesi filtre olması gerekir, ya da dizin hiç kullanılmaz.
  2. Dizin bırakmak ve oluşturmak ve istatistiklerini daha sonra tekrar güncellemek yine de yapacaklarını varsaydığımız güncellenmiş planları üretmek için yeterli olmayabilir. Bazı durumlarda yalnızca yeterince yüksek bir iş yükü SQL Server'ı planları yeniden değerlendirmeye zorlar.
  3. Sadece sağduyu ve mantık ile belirlenmesi zor olan yürütme planlayıcısının işlevselliği için bazı ekzotikler vardır. Farklı sorguların binlerce koddan türetilen varyasyonu bile, görünüşte yararsız dizinler, kritik sorgularda kullanılan bazı istatistik ve sorgu planlarında yardımcı olabilir.

Sonunda, bu değişiklikler geri alındı. Dolayısıyla, filtrelenmiş dizinler güçlü bir araçtır, ancak bu sütunlardan hangi verilerin getirildiğini tam olarak anlamanız gerekir. Alan sorunlarının yanı sıra normal dizinlerin uygulanması oldukça kolay olduğunda, filtrelenmiş dizinler çok özelleştirilmiş çözümleri temsil eder. Kesinlikle normal bir endeksin yerine geçmezler, ihtiyaç duydukları bu özel durumlarda bir uzantısıdırlar.


Dizin oluşturma stratejinizi de yeniden incelemek isteyebilirsiniz. Yüzlerce tek alan dizininiz varsa, bu muhtemelen uygun değildir.
JNK

Bunlara duyulan ihtiyaç, veritabanının kısmen başka bir sistemden miras alınmasından kaynaklanmaktadır. Varsayılan olarak, bazı büyük tablolarımız ve hiç kullanılmayabilecek birkaç büyük sütunumuz vardır, bu da bu büyük miktarlarda dizinlenmiş NULL değerlerin çoğunu üretir. Tek alanlı dizinlere gelince, her bir yabancı anahtarın dizine alınması gereken temel gereksinimden oluşturulurlar ve bunların çoğu bu sütunlarda çoğunlukla veya yalnızca NULL değerler içerir.
Kahn

Yanıtlar:


8

Çok ilginç bir yaklaşım. Yaratıcılık için oyum.

Alanı geri kazandığınızdan, orijinal dizinlerin artık yerinde olmadığını varsayıyorum? Filtrelenmiş indekslerin dezavantajları:

Pratik açıdan, filtrelenmiş dizinlere son derece dikkatli olmanız gerektiği anlamına gelir, çünkü bunlar genellikle korkunç sorgu planlarına neden olur. Onları işe yaramaz olarak adlandıramayacağım, ancak onları geleneksel dizinlere ek olarak görüyorum, yerine (yapmaya çalıştığınız gibi) değil.


Msgstr "Sorgu parametrelendirmesi filtrelenmiş dizinlerle çalışmaz". bu muhtemelen seçeneği ile düzeltilebilir (yeniden derleme)
MichaelD

2

Thomas Kejser bu konuya çok iyi cevap veriyor .

Sadece 2 sent eklemeyi düşündüm.

Filtrelenmiş dizinde nerede olarak sorgunuzdaki nerede yan tümcesiyle tam olarak eşleştiğinizde yalnızca (yürütme planında gösterilen) kullanılan bazı filtrelenmiş dizinler gördüm.

dizine alınmış görünümleri kullanmaya çalıştınız mı? seyrek sütunlar ?

Sadece iç eklemleriniz olduğu sürece, filtrelenmiş dizinlerinizin nerede (ler) ini içeren bir dizinlenmiş görünüm oluşturabileceğinize ve bunun yerine görünümü kullanabileceğinize inanıyorum.

Birden fazla görüş olabilir. Ancak kümelenmemiş dizinlerde olduğu gibi, çok fazla kişi yazınızı yavaşlatacaktır.

Deneyimlerime göre, okumada iyi kazançlar elde edersiniz, ancak tablolar çoğaltmada yer alıyorsa, yazıları (ekler ve güncellemeler) özel olarak izlemeniz gerekir.

Bununla birlikte, asıl endişenizi anladığım için, the null valuesbu nedenle dizinlerinizdeki SPARSE sütunlarını öneririm .

Seyrek sütunlar özellikle filtrelenmiş dizinler için uygundur

Seyrek sütunların reklamını yaptığım için, size sınırlamalarını da söylemezsem iyi hissetmezdim:

Seyrek sütunları olan tablolar tasarlarken, bir satır güncellenirken tablodaki her boş olmayan seyrek sütun için 2 baytlık ek bir ek yük gerektiğini unutmayın.

Bunun sonucu olarak

ek bellek gereksinimi, bu bellek yükü de dahil olmak üzere toplam satır boyutu 8019'u aştığında, güncellemeler beklenmedik bir şekilde 576 hatasıyla başarısız olabilir,

ve hiçbir sütun satırın dışına itilemez.

> Bigint türünde 600 seyrek sütun içeren bir tablo örneğini düşünün.

571 null olmayan sütun varsa, diskteki toplam boyut 571 * 12 = 6852 bayttır. Ek satır ek yükü ve seyrek sütun başlığı eklendikten sonra, bu yaklaşık 6895 bayta yükselir. Sayfada hala yaklaşık 1124 bayt kullanılabilir. Bu, ek sütunların başarıyla güncellenebileceği izlenimini verebilir. Bununla birlikte, güncelleme sırasında, bellekte 2 * (boş olmayan seyrek sütun sayısı) olan ek yük vardır. Bu örnekte, ek yükü - 2 * 571 = 1142 bayt - dahil etmek, diskteki satır boyutunu yaklaşık 8037 bayta çıkarır. Bu boyut, izin verilen maksimum 8019 bayt boyutunu aşıyor. Tüm sütunlar sabit uzunlukta veri türleri olduğundan, satır dışına itilemezler. Sonuç olarak, güncelleştirme 576 hatasıyla başarısız olur.

Yukarıdaki bağlantı hakkında daha fazla ayrıntı, ancak ben de bu uyarıyı buraya göndermeyi tercih ederim:

Bir sütunu seyrek durumdan seyrek olmayana veya seyrek olmayan biçimden değiştirmek için sütunun depolama biçiminin değiştirilmesi gerekir.

SQL Server veritabanı altyapısı, bu değişikliği gerçekleştirmek için aşağıdaki yordamı kullanır:

1 - Tabloya yeni depolama boyutu ve biçiminde yeni bir sütun ekler.

2 - Tablodaki her satır için eski sütunda depolanan değeri yeni sütuna günceller ve kopyalar.

3 - Eski sütunu tablo şemasından kaldırır.

4 - Tabloyu (kümelenmiş dizin yoksa) yeniden oluşturur veya kümelenmiş dizini, eski sütun tarafından kullanılan alanı geri kazanmak için yeniden oluşturur.


1
Selam. Yıpranmaya biraz geç ama evet, bu konuda açıklanan yaklaşımı uzun zaman önce terk ederken, son zamanlarda daha seçici bir yaklaşımla geri döndük. Temel olarak, indeksleri tablo bazında bir tablo üzerinde teyit etmek için istatistik kullanımı ve iş modeline baktık. Daha sonra normalin yanına yeni bir filtrelenmiş dizin ekleyerek test edildi ve birkaç hafta boyunca hangisinin kullanıldığını görmek için kontrol edildi. SADECE filtrelenmiş endekslerin yeni planlarda kullanıldığını doğruladıktan sonra, filtrelenmemiş normalleri bıraktık.
Kahn

1
Ayrıca, birkaç sütunu seyrek türlerle değiştirdik. Bununla birlikte sorun, MSDN'den göreceğiniz gibi, bir sütun türünü seyrek olarak değiştirmenin temel olarak tüm kümelenmiş dizini yeniden oluşturulmaya zorlamasıdır. Bunu büyük, karmaşık tablolar için oldukça ağır hale getirir. Bu nedenle, kısıtlamaları ve tabloyu yeniden adlandırdık, aynı model ve orijinal adla ancak seyrek sütunlarla yeni bir tane oluşturduk ve ardından verileri uygun gruplar halinde yeni tabloya aktardık. Sonra bir kez her şeyin yolunda olduğunu ve tüm dizinler ve FK'ler tekrar yerinde olduğunu kontrol, eski tabloları düştü.
Kahn

1
Ayrıca, bazı durumlarda sayfa sıkıştırmayı kullanmak çok tercih edilirdi, bunun yerine bunu yaptık. Ayrıca, seyrek rotaya gitmekten çok daha hızlı hale getirmek için mevcut kümelenmiş dizini DROP_EXISTING = ON ile kolayca oluşturabileceğiniz için de kullanışlıdır. Özellikle endeksleri ve FK'leri yeniden yönetme zahmetinden kaçındığı için.
Kahn
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.