Friday, June 24, 2011

PostgreSQL : Postgres Diye Okunur

Eğitim notlarımdan derleme bir yazı yazacağım:

1970'lerde geliştirilmeye başlanmış. Yapısı ana olarak 3 kademeli. En üstte tek çekirdekte çalışan bir postmaster prosesi var. En zayıf özelliği galiba bu, çoklu çekirdek desteği (multi cpu, multi core) yok. Bu postmaster'ın altında shared memory var.

Shared memory'nin yapısında da üç unsur var,
- shared buffers
- wal (writer ahead log) buffers
- process array

Bir işlem ise 4 adımdan oluşuyor: rewrite, parse, plan, execute.

Örneğin, bir insert yapacağız. Cümlemiz, her seferinde bu 4 adımdan geçip execute sonucunda veri, yazılmaya hazır halde bellek uzayından disk uzayına geçiyor. Bu disk uzayında da doğrudan veritabanı ile ilgili tabloda değil, xlog adı verilen transaction log dosyalarına yazılır. Sonrasında arka planda, Postgres bu xlogları esas db'ye geçirir imiş. Filesystem ile çok fazla haşır neşir olmaması ve bu bölünmüş yapı da performans artışı sağlatabiliyor.

Şöyle ki, xlog dosyalarını çok çok hızlı bir diskte (fiziksel olarak ayrı bir diskte) tutarsınız, hatta ramdiskte bile olabilir bu; veri dosyalarınızı raidlenmiş hızlı random okuma yetisine sahip bir disk yapısında bulundurursunuz örneğin. Böylece şahane hızlı olurmuş.

Xlog'un avantajı şu: esas veritabanı dosyalarına veriyi yazmadan, bu xlog'a veri yazıldığı anda, kullanıcıya "işlem başarılı" yanıtını dönüyor. Çünkü olası bir kesintide (elektrik kesintisinde mesela, fiks örnek), db açılırken, bu xlogları tarayıp, eksik kalan, öbür tarafa geçirmediği, yansıtmadı işlemleri evvela aktarıp toparlıyor kendini.

Ayrıca çekirdeği itibariyle, veritabanı kendinden performans optimizasyonuna sahip. Özellikle queryleri indexlerle çekme konusunda çok çok başarılıymış. Bununla birlikte "hint" olayı yok querylerde. Oraclecılar, raporlamacılar veya developerlar (realtime dataya bakmak gerekiyor bazen) özellikle selectlerde bol bol hint kullanır bu yüzden sevinebilirler de, üzülebilirler de.

Dediğim gibi, Postgresql'de ise Oracle'daki gibi hint olayı yok (yani bu prosesi 8 thread çalıştır, index olarak şunu değil bunu kullan gibi ipuçları kullanamıyoruz). Postrgres tabanı kullanan, onun üzerine yazılmış bazı sistemlerde (örneğin enterprisedb) bu özellik sonradan getirilmiş olsa da, temelde yok. Sebebini de esas geliştiricisi şöyle açıklıyor: "bizimkinden daha optimize çekemezsiniz." o derece iddialılar sorgu konusunda.

Postgres'in bir de `mvcc` desteği var (Oracle vs diğer rdbmslerde de var, o ayrı). Buna göre yapılan işlemler, eşzamanlı farklı transactionlarda tutarlı sonuçlar veriyor, güzel bir şey bu.

Bazı dikkat edilmesi gereken özellikleri de varmış. Örneğin block size, disk için 8 kb şeklinde fikslenmiş. Bu bloklar da yarım parçalı kullanılamıyor. Işletim sistemleri dersi alanlar belki hatırlar (bilgisayar mühendisliği okumadıysanız üzgünüm), veri bu bloklara bölünmeden yazılabiliyorsa, yani bloklar verimli kullanılırsa daha az io yapılır. Aynı durum burada da geçerli. Örnekleyelim. Diyelim ki blok size 8 olsun (byte), 1000'le çarpıldığını düşünün:

Tablo yaratıyorsunuz, 5 sütununuz var.
C1 varchar 5
c2 varchar 6
c3 int 4
c4 varchar 3
c5 int 2

Bunlar 8'lik olarak aşağıdaki şekilde dizilecektir (boş blok |--------| ile gösteriliyor)
|5*c1 + ---|
|6*c2 + --|
|4*c3 + 3*c4 + -|
|2*c5 + ------|
İsraf olan toplamda 3+2+1+6 byte var. Bu da disk kafasının daha çok oynaması, daha çok i/o demek.

Şayet bu tablo şu şekilde tanımlanırsa,
c1 varchar 5
c4 varchar 3
c2 varchar 6
c5 int 2
c3 int 4

Dizilim değişiyor,
|5*c1 + 3*c4|
|6*c2 + 2*c5|
|4*c3 + ----|


3 blokta iş bitecekti, israf 4 byte, i/o daha az, performans daha yüksek.

Dikkatli kullanılması gereken bir de explain hususu var. "Explain analyze select * from t1" derseniz, önce sorgu çalıştırılır, sonra açıklaması yapılır. Tehlikeli, çünkü delete veya update benzer şekilde "explain analyze" ile birlikte kullanılırsa, veriyi siler. Bunu önlemek için illa ki begin / rollback yapısını kullanmak gerek. Alışkanlık meselesi.

Vacuum olayı var değinilmesi gereken.

Insert yaparken en alta yeni bir satır ekliyor diyelim.

Delete yaparken aradan (yukarılardan bir yerlerden) eski bir satırı siliyor. Silmek için de başına bir invisible flagi ekliyor. (Dosya sistemine benziyor bu yapı) ve tam olarak, fiziksel olarak silmiyor veriyi. Ama selectlerde, count'larda bu veri sayılmıyor. Silinmiş yani üst katmanda.

Update ise, yapısı itibariyle delete ve insert'ten oluşuyor gibi düşünülebilir. Önce değiştirilecek eski veri invisible ediliyor (siliniyor) sonra en alta yeni bir satır ile ilgili verinin güncellenmiş hali yazılıyor. Eskisi görünmez, yenisi görünür halde.

Vacuum işte burada devreye giriyor ve bu silinen (güncellenip de eskiyen veriler de aynı şekilde) sistemden atılıyor. Autovacuum ortamında belirli zaman aralıklarında (bunun eşik değerleri var elbet) çalışarak disk üzerinde aşırı zıplamalara yol açacak, eski veri kirliliği birikimini engelleyebilir. Vacuum sonrasında yerleri boşalan yerlere, yeni gelen datalar insert ediliyor, db derli toplu kalıyor bu sayede.

Prosedür yok, her şey fonksiyon. Böyle bir özelliği var.

Değişkenler ve tablo adları, tamamen küçük harf. Isterseniz "tablo" deyip büyük harflerle tablo isminde veritabanı yaratabilirsiniz, erişirken yine çift tırnak içinde aynı şekilde yazmanız gerekiyor bu durumda. Bu noktada standart sql'den ayrılıyor. Oracle'da her şey büyük harfti mesela.

Ip, mac ve benzeri dataları tutmak için buna özel verip tipleri var. Char tipinden bunları saklayıp, sonra uygulama tarafında (string operasyonları ile) parçalayıp incelemektense, bu şekilde tutmak daha güzel. Geometrik veri tipleri var, bir de bir sonraki sürümde coğrafi konumla ilgili bir veri tipi çıkarıp, en yakındaki coğrafi konumu gösterebilecek bir altyapı üzerinde çalışılıyormuş.

Partial ve functional indexler var. Indexlerde detaylı regular expression kullanabilme şansımız varmış.

Daha başka şeyleri de var da onları yazmaya üşendim.

Eğitim notlarımdan şimdilik bu kadar.

Yaklaşık 10 senedir çeşitli veritabanlarına bir şeyler yazıp çizen bir kimse olarak ise söyleyebilirim ki, "neden olmasın". Dba değilim, yazılım tarafındayım işin ve ara katmanda Oracle'a yaptırdığım işlerin aynısını Postgres'e de yaptırabiliyorum. Geçen sene sıfırdan yazdığım bir projede, Oracle olması planlanan veritabanı son anda Postgrese dönmüştü ("bunu kullanacaksın", "peki patron" şeklinde bir emrivaki ile). Projeyi yazma süremin yarısı kadar bir süre Postgres'i inceleyip, bağlantı yaratacak sınıfları bulmak, sunucu sistemini ona göre konfigüre etmek, yeni veritabanında tabloları racona uygun veri tipleri ile yaratıp, gerekli optimizasyonları yapmakla geçti. Onun dışında sentaksını öğrenip, Oracle muadili kodları uygulamada (java) kullanma aşaması birkaç saat. Onda da nvl yerine coalesce yazmak yaptığım en karmaşık işti, o kadar.

Mysql'i bırakalı yıllar oldu ama, Oracle ile 3 senedir bilfiil uğraşan biri olarak hiçbir eksiğini görmediğimi söylemeliyim. Kullanın, deneyin, çekinmeyin. Ustaları da diyor ki: dünyadaki gelecek veritabanı yönetim sistemi, Postgres olacakmış. Çünkü açık kaynak, yaşasın özgürlük.

Monday, June 06, 2011

Web Application Developing on JBoss, Netbeans and Maven

Jsp sayfalarındaki değişimleri gerçek zamanlı olarak görebilmek için, JBoss'a uygulamaların açık (exploded) olarak deploy edilmesi gerekiyor. Ancak JBoss'un deploy dizini ile NetBeans'in derlediği Maven projesi /target/ dizini malesef aynı değil. JBoss üzerinde de, Weblogic'teki gibi "I will make the deployment accessible from the following location." opsiyonu olmadığından; bu sorunun üstesinden gelmek için Windows'un symbolic link yapısını kullanmak işe yarayabilir. Symbolic Link oluştururken dikkat edilecek husus, klasörün isminin .war şeklinde bitmesi. Böylece JBoss deploy dizinini tararken, bu "hede.war" ismindeki klasörün, açık durumda bulunan bir web application olduğunu anlıyor. Şöyle ki;

D:\>cd D:\jboss\server\default\deploy
D:\jboss\server\default\deploy>mklink /D deneme.war D:\svn\deneme-web-app\trunk\target\deneme

Böylece IDE'nizde 1 harfini değiştirdiğiniz Jsp sayfanız, anında target dizinine gönderiliyor, JBoss da bunu okuyarak değişimleri exploded deploy edilmiş war'unuza yansıtıyor. IDE üzerinde yaptığınız değişikliği zahmetsizce (tekrar clean & deploy, target dizinini aç, kopyala, JBoss deploy dizinine war at vs yapmadan), sadece tarayıcıdan F5 yaparak görmek çok güzel.

Niye İngilizce başlık yazdım bilmiyorum.