18 Aralık 2020 Cuma

SQL Server'da Bir Tablonun Veritabanını Bulmak

Merhaba Arkadaşlar,

Kullandığım bir kod bloğunu sizinle de paylaşmak istedim. SQL Server'da birkaç instance üzerinde yüzlerce veritabanınız olabilir. Bazen öyle zamanlar oluyor ki, elinizdeki tablonun hangi database üzerinde yer aldığını bilemeyebiliyorsunuz.

Aşağıdaki gibi bir kod bloğu ile bu dertten kurtulabilirsiniz. :)

sp_msforeachdb 'use [?] select db_name() db,* from sys.tables where name like ''%TableName%'''

Sarı olan kısma tablonuzun adını yazabilirsiniz. İşinize yarayabilir.

Görüşmek üzere.

13 Aralık 2020 Pazar

Veri Ambarında (DWH) Neden SK(Surrogate Key) Üretilir?

Merhaba Arkadaşlar,

DWH işinde, özellikle modelleme yaparken, kaynak sistemdeki arkadaşlara bir mimari kurduğumuzu anlatmak sıkıntılı bir iş. Kendileri webservise iki parametre geçtiği için, dwh etkisini de bu şekilde düşünüyorlar. :)
Girizgahı savunma-vari şekilde yaptıktan sonra, konumuza gelelim: Surrogate Keys(vekil anahtar imiş Türkçesi). 

Malumunuz, OLTP sistemlerde genelde normalize tutulan verileri incelediğimizde, genelde bir primary key olduğunu görebilirsiniz. Bu kimi zaman bir sequence, kimi zaman bir timestamp, kimi zaman bir kombinasyon(işlemtarihi-000-kurum kodu-işlem tipi-seq vb) olabiliyor. Tıpkı OLTP sistemlerde olduğu gibi, Veri Ambarı dünyasında da bir surrogate key kullanımı mevcut. Surrogate Key'ler genelde herhangi bir anlam içermeyen, sequental yapıdaki numeric alanlardır. 

Peki kaynak sistemlerde bir business key varken(ki ona natural key de diyoruz), neden bir daha SK üretiyoruz?

İlk belirtmemiz gereken neden, kaynak sistemlerdeki bu business key'ler(natural key), o sistem içinde bir anlamı olabilir. Örneğin bir şahıs şirketidir. Key olarak TCKN tutuyordur. Ancak sonrasında mevzuat değişmiştir, artık VKN(vergi no) almıştır kendisine. Dolayısıyla datanın şekli şemali tipi vs değişebilir. Bu kaynak ile ilgili bir durum. Absürt örnek vereyim, TCKN yerine de 'bjk1903' gibi bir değer de tutabilirler. Bunu izlemek, değişimleri yönetmek sıkıntı. Üstüne üstlük, bu keyin geçtiği, join kurduğu tüm alanları bulup dwh'te düzeltmek zorunda kalabilirdik. Bu nedenle business key'leri genelde string bir data tipinde tutup, karşılığında SK değer üretmek mantıklıdır. 

Bunun dışında bir diğer neden de, az önce de yazdığım üzere, bus,ness key olarak, upuzun bir kombinasyon tutulabilir. Tabi bu şekilde çok fazla yer kapalayacaktır. Dolaylı olarak performans etkisi yaratacaktır. SK ile hem yerden tasarruf edecek hem de performans sorunu yaşamayacaksınız.

Belki de kritik bir sıkıntı daha da şu: kaynakta, örneğin transactionı fazla olan yapılarda, belli bir süre sonra, truncate edilip, bu natural key'ler en baştan başlatılabilir. Bu çok riskli bir durumdur. DWH data dilmeyip, history'i saklama konusunda hassastır, malumunuz. Bu şekilde büyük işlem karmaşaları ortaya çıkabilir.

Bunun gibi nedenlerden ötürü, kaynak(operasyonel) sistemlerden çekilen tablolar için, veri ambarında genelde bir SK değeri üretilir.

Sonra görüşürüz.

5 Aralık 2020 Cumartesi

Kanban: Classes Of Services

Selamlar Herkese,

Kanban metodolojisinde, backloga gelen işleri yönetmek için bir ritüel daha mevcut: Classes of Services.
Bu yöntemle gelen işleri önceliklendirmek, sıraya almak ve planlamak sağlam bir temele oturuyor. Bu konsept ile işi oturttuğunuz kategoriye göre cost of delay, yani gelen işin maliyetini daha net görebilirsiniz.

Genel anlamda 4'e ayrılır:
1. Expedite
2. Fixed Date
3. Standart
4. Intangible

Elinizde bir iş var ve sprinte alamadınız örneğin. Bu iş size kaça patlar? İşte bu konsept ile bir tahminleme yapabilirsiniz.
Önce internetten bulduğum ve çok güzel özetleyen resim ile göstereyim.

Expedite: Production bug gibi düşünebilirsiniz. Sizde bir günde milyon dolar bile kaybettirebilir. Bu şekilde bir iş geldiğinde, WIP Limit falan kalmaz ortada. Bu iş ya da işler diğer tüm işlerin önüne geçer.

Fixed Date: Regülatif değişiklikler gibi düşünebilirsiniz. Diyelim ki ssl ile bir devlet kurumuna erişiyorsunuz. Kurum kararınca 2 ay içinde TLS'e geçmeniz istendi. Eğer gecikirseniz, yaptırım ve maddi zararlar ortaya çıkar. Planlamak ve atlamamak gerekir, bu sınıftaki işleri.

Standart: Klasik standart müşteri talepleridir. Sıradaki iş direkt çekilir mantığı yani.

Intangible: Aciliyeti olmayan ama yapmazsan ileride masraf çıakrtabilecek altyapı değişimleri gibi düşünebilirsiniz. Uygun bir zaman dilimine planlanabilecek işlerdir.

Sonra görüşürüz.


SQL'de Join Çeşitleri

Merhaba Arkadaşlar,

Temel bir konuya değinmek istiyorum bugün. Zira mail üstünden gelen sorularda özellikle işin outer join kısmında bir kafa karışıklığı olduğu görülüyor. Oracle üzerinden anlatacağım konuları, gidişata göre ayrı başlıklar da açabilirim.

JOIN dediğimiz kavram, birden fazla tablodan veri almamızı sağlayan ifadeler, bağlaçlardır. 

JOIN sorgusu çalıştırırken, Oracle'da Optimizer'ın bazı kontrolleri vardır. Join'i yaparken index kullanılacak mı; full table scan mı gidecek(yani tüm tabloyu tek tek gezecek mi; yoksa nokta atışı yapacak mı gibi çevirebilirim burayı), bunu belirler. Akabinde join'e giren tablo sayısı 2'den fazlaysa, join order'ı yapar. Yani önce küçük tabloları joinler, sonra buradan dönen data set'i üstünden büyük tabloya gider. Bu sayede sorgu performansında artış amaçlanır. Son olarak da yazdığımız join'e bağlı olarak arka planda hangi join method'u(hash-sort merge-nested loop) kullanılır, bu belirlenir. Yöntemlere kısaca ayrı bir başlıkta değineceğim.

Gelelim sql önyüzünde, Toad-plsql developer-sql plus gibi bir arayüzde yazdığınız join türlerine.
1. Inner Join
2. Left Join (Left Outer Join)
3. Right Join (Right Outer Join)
4. Full Join (Full Outer Join)

Öncelikle örnekte kullanmka üzere iki tablo yaratalım.
JoinTableTest1 tablosu takım bilgisi tutuyor olsun.

JoinTableTest2 tablosu da oyuncuları tutuyor olsun; TakımID de foreign key'i ve bu kolon üstünden join kuralım. Tablolar ve alanlar çok uyduruk. :) Joini anlatmak için hızlıca oluşturdum, mantıksal tasarımı sıkıntılı; join'e odaklanın lütfen. :)


INNER JOIN:
İki tablonun joininde eşleşen kayıtlar için sonuç döndüren join türüdür. 
select t1.TakimAdi,t2.OyuncuAdi from JoinTableTest1 t1, JoinTableTest2 t2
where  t1.TakimID=t2.TakimID --bu eşitlikle inner join veriyoruz.
--Yani her iki tabloda TakimID'si eşit olan oyuncuları getiriyor. 


İnternetten aldığım resimle olayı açıklıyorum. 
Örneğimizde iki tabloda takımIDsi aynı olan kayıtlar getiriliyor.

Aynı sorguyu = operatoru yerine, INNER JOIN ile de yazabilirsiniz:
select t1.TakimAdi,t2.OyuncuAdi 
from JoinTableTest1 t1 INNER JOIN JoinTableTest2 t2
ON t1.TakimID=t2.TakimID

Bu da aynı sonucu üretir:



LEFT JOIN:
Kitabi anlatmayacağım. :) Joinin solundaki tablonun tamamı listelenir. Olayın mantığının temeli bu. Eğer select ifadesinde, sağdaki ikinci tablodan kolonlar varsa, solda olup, sağda karşılığı olmayan kayıtlar için, selectteki o kolonlar null gelir. Örnekle açıklamak en güzeli. :)

select t1.TakimAdi,t2.OyuncuAdi 
from JoinTableTest1 t1 LEFT JOIN JoinTableTest2 t2
ON t1.TakimID=t2.TakimID 

Şimdi örnek üstünden açıklayalım. Soldaki tablo nedir: JoinTableTest1. Bu tabloda takımlar vardı. Demek ki eşleşse de eşleşmese de, bu tablonun tüm kayıtları gelecek. Eşleşen 11 kayıt, zaten inner join'de de görmüştük, kafadan gelmiş. Ancak son 2 kayda dikkat buyurun. Oyuncuları tutan JoinTableTest2 tablosunda Trabzonspor ve Galatasaray'lı oyuncu yoktu. Yani eşleşme yok. Bu nedenle OyuncuAdı alanları NULL bir şekilde, bu iki takım da gösterilmiş. Left Join tam olarak böyle bir dünya. :)

Bu sorguyu ben yukarıdaki gibi yazmaya üşeniyorum. (+) ile yazıyorum. Bu şekilde yazmak isteyeneler için:
select t1.TakimAdi,t2.OyuncuAdi 
from JoinTableTest1 t1, JoinTableTest2 t2
where t1.TakimID=t2.TakimID(+)

Eşitliğin t2 kısmına (+) konmuş. Demek ki t1'in hepsini alacağız, şeklinde aklınızda da tutabilirsiniz. :)
Oracle docs'u yerle yeksan ettik. Kendimi eski hbb kanalındaki beyin egzersizci abimiz gibi hissettim. :)

Şekilsel gösterimi de şöyle:



RIGHT JOIN:
Joinin sağındaki tablonun tamamı listelenir. Left'in aynı mantığı var burada da. Eğer select ifadesinde, soldaki birinci tablodan kolonlar varsa, sağda olup, solda karşılığı olmayan kayıtlar için, selectteki o kolonlar null gelir. Ben direkt örneğe geçeyim; en temiz öyle anlaşılır.

select t1.TakimAdi,t2.OyuncuAdi 
from JoinTableTest1 t1 RIGHT JOIN JoinTableTest2 t2
ON t1.TakimID=t2.TakimID


Sağdaki tablomuz nedir: JoinTableTest2. Oyuncu bilgilerini tutan tablo. Eşleşen 11 kayıt yine geliyor. İlave olarak sağdaki oyuncu tablosunda TakımID'si 21 ve 26 olan iki oyuncu bilgisi de geliyor. Yalnız bu takımID'ler, JoinTableTest1 tablosunda yok. Bu nedenle TakımAdı bilgisi boş geliyor. Ancak sağdaki tablonun tüm kayıtları listelendiğinden, Nouma ve İlhan kayıtları, eşleşmese de sonuç kümesinde geliyor.

Tıpkı Left Join'de olduğu gibi, Right Join'de de, aşağıdaki gibi yazabilirsiniz.
select t1.TakimAdi,t2.OyuncuAdi 
from JoinTableTest1 t1, JoinTableTest2 t2
where t1.TakimID(+)=t2.TakimID


Aynı şekilde, t1'in yanında (+) olduğundan, t2'nin hepsi listelenir gibi düşünebilirsiniz.
Şeklini de verelim right outer join'in:


FULL JOIN:
Left Join ve Right Join'in birleşimi gibi düşünülebilinir. İki tablodaki tüm kayıtlar döner. Karşılığı olmayan kayıtlar için, alanlar NULL döner.

select t1.TakimAdi,t2.OyuncuAdi 
from JoinTableTest1 t1 FULL JOIN JoinTableTest2 t2
ON t1.TakimID=t2.TakimID


Gördüğünüz üzere, hem right'taki hem de left'teki kayıtları getirdi. 
Bu join tipini de şu şekilde görselleştirebiliriz; tabi ki kaynak yine internet:

Optimizer'da görülecek olan join tiplerine daha sonra değinelim; okunurluk düşüyor.

Sonra görüşürüz.