Viewda bir tablonun tüm kolonlarını almak
SQL-Server 2005’te viewlar ile ilgili yaşadığımız ciddi bir problemi sizlere aktarmaya çalışacağım. Her zaman yeni bir kolon eklenmesi muhtemel demografik bir tablomuzdaki tüm alanları, bir view içerisinde görmek istiyor olalım. Muhtemelen oluşturacağınız view kodu aşağıdaki şekilde olacaktır. (table_a bu örnekteki demografik tablomuz olsun)
Oluşturduğumuz bu viewı select edersek, şöyle bir tablo ile karşılaşacağız.
Field (b tablosundan geliyor)
Bu viewdan field alanı Y olan kaydı select edelim.
select * from vw_test where field = 'Y'
Şimdi en başta bahsettiğimiz şekilde a tablosuna Field4 isimli bir kolon ekleyelim ve değerini 1 yapalım.
alter table table_a add Field4 int default 1
update table_a set Field4 = 1
Yukarıda çalıştırdığımız, viewdan field alanı Y olan kayıtları select ettiğimiz cümleyi tekrar çalıştıralım. Sonuca şaşıracaksınız J
Hiçbir kayıt gelmedi… Ve dikkat ederseniz, table_a’dan * ile select etmemize rağmen, Field4 alanı da görünmüyor.
Tüm viewı tekrar select edelim.
Field kolonunda görüldüğü gibi değerler X,Y,Z şeklinde gelmedi. Viewı drop edip tekrar create edelim, tekrar tüm viewı select edelim.
Viewı tekrar oluşturduktan sonra hem beklediğimiz Field4 alanı listeye geldi, hem de b tablosundan gelen X,Y,Z değerlerini görebiliyoruz. Peki table_a’dan tüm alanları * ile almamıza rağmen neden listeye gelmedi?
1. View oluşturulduğunda execution plan, kolon indexleri ile kaydedildi.
2. Table_a’ya bir kolon ekledik, eklediğimiz kolon, table_b’den gelen field kolonunun viewdaki indexine sahip olmuş oldu. Bu yüzden select ettiğimizde b tablosundaki değerler değil, a tablosundaki field4’ün değerleri geldi. Ama kolon başlığı hala viewda tanımlandığı şekilde gözüküyor.
3. Viewı tekrar oluşturarak (ya da alter ederek) execution planı yeni indexler ile tekrar oluşturduk.
4. Selecti tekrar yaptığımızda her şey düzeldi.
- View oluştururken * ile tüm kolonları istenen tabloları, select listesinin sonuna ekleyin. (select a.*, b.field yerine select b.field, a.*)
- Viewlarda kullanılan demografik tablolara bir kolon eklendiğinde, viewları refresh ederek execution planın yenilenmesini sağlayın.
- Kesin ve hatasız çözüm için, view içerisinde tablonun alanlarını * ile değil, isimlerini yazarak select edin. (select a.id, a.field1, a.field2, a.field3, a.field4, b.field). Tabloya yeni bir kolon eklendiğinde, bu kolonu viewa da ekleyin.
Varsayım: viewı tekrar oluşturmadan şu cümleyi çalıştırdığımızı hayal ederseniz, durumun ne kadar vahim olduğunu anlayabilirsiniz J
where exists(select 1 from vw_test t where t.id = x.id and t.field = 1)
Gönderen Uğur Tılıkoğlu zaman: 19:14 Hiç yorum yok:
T-SQL'de exists optimizasyonu
Çalışmakta olduğum kurumun sevkiyat sistemi üzerinde; son kullanıcı, blok işlem ve transaction sayısı arttıkça sistem iyice hantal bir yapıya bürünerek insanları zor durumda bırakıyor idi. Saatlerce süren işlemler, timeout ve deadlock'a düşen transactionlar, özellikle bayram döneminde sevkiyat yoğunluğu 5-6 kat arttığından mutlaka müdahale edilmesi gereken bir yara haline gelmişti.
Kim bilebilirdi ki; basit bir exists cümlesinin belki de saniyeler sürecek bir işlemi dakikalara, hatta büyük bloklar için saatlere çıkartabileceğini?
SQL Server Profiler ile işlemin trace'ini aldığımızda aşağıdaki basit exists kontrolünde takılmalar olduğunu tespit ettik.
if exists (select 1 from tb_DepoToplamaBaslik b where exists(Select 1 from inserted i (nolock) where i.PartiNo = b.PartiNo) or exists(Select 1 from deleted d (nolock) where d.PartiNo = b.PartiNo) ) begin ... end
Görüldüğü üzere bir trigger üzerinde bulk insert, update ya da delete işlemi olduğunda bu kontrole giriliyor. İlk olarak tb_DepoToplamaBaslik tablosundaki PartiNo alanı için clustered index oluşturmayı denedik. Bu ilk etapta performans artışı sağlasa da, yine de istediğimiz sonuca ulaşamadık.
tb_DepoToplamaBaslik tablosunda 650.000 satır bulunduğunu ve sürekli arttığını, bulk işlemlerde ise en fazla 10.000 satırlık işlemler yapıldığını göz önüne alarak aşağıdaki şekilde bir düzenleme yaptık.
if exists(select 1 from inserted i where exists(Select 1 from tb_DepoToplamaBaslik b (nolock) where i.PartiNo = b.PartiNo)) begin ... end else if exists(select 1 from deleted d where exists(Select 1 from tb_DepoToplamaBaslik b (nolock) where d.PartiNo = b.PartiNo)) begin ... end
İlk kısımda görülen "or" için if-else if bloklarına ayırma işlemi ve daha düşük satırlı tabloyu ilk select içinde, yüksek satırlı tabloyu exists içerisinde yazma değişikliklerinden sonra dramatik bir artış gözledik. Yaptığımız işlem ilk etapta 30 dk sürer iken, bu optimizasyonla birlikte 1 sn'nin de altına düştü.
Çok basit olduğunu düşündüğümüz kodların, hiç beklemediğimiz anda bizi ters köşeye yatırabileceğini unutmamak gerek.
Gönderen Uğur Tılıkoğlu zaman: 16:45 2 yorum:
Scratch için turntable ayarları
Başarılı bir scratch performansı için turntable'ın tone arm ayarları çok önemlidir. İğnenin plak üzerinde yapacağı fazla ağırlık, scratch esnasında ağır seslere sebep olabileceği gibi, plaklarınızın da daha çabuk eskimesine yol açar. Turntablism'in efsanelerinde Q-Bert'in anlattığı doğru turntable ayarlarının nasıl yapıldığını aşağıdaki videodan izleyebilirsiniz. http://youtube.com/watch?v=JIpRQ29PQS8 Özetlemek gerekirse; tone arm'ın ağırlık aparatı tone arm'ın en dış kısmı ile sıfırlanacak şekilde ayarlanır, yükseklik 3.5 ve anti-skating ayarı ise 0 olarak sabitlenir. Başarılı çalışmalar...
Gönderen Uğur Tılıkoğlu zaman: 15:11 Hiç yorum yok:
Blogger.com üyeliğini yıllar önce almış, ancak blog oluşturmak için yeterli zamana sahip olamamıştım. Artık yazılım teknolojileri ve müzik çalışmalarım hakkında paylaşmak istediklerimi burada yayınlamayı düşünüyorum. Darısı başınıza ;)
Gönderen Uğur Tılıkoğlu zaman: 15:47 Hiç yorum yok: