MySQL türkçe desteği: Collation ve character set nedir?

MySQL 4.1’den itibaren türkçe karakter işi karıştı. “SET NAMES latin5” ile çözdük bu problemi gerçi ama yine de sistemin nasıl çalıştığını bilmezseniz sorun yaşayabilirsiniz. O yüzden MySQL’in karakter seti ve collation hakkında birşeyler yazayım istedim.

Tanımlar

Konuyu kavramak için önce tanımları ele alalım. Bilmemiz gereken iki tanım var: “Character Set” ve “Collation”

Character Set (Karakter Seti)
Adından anlayabileceğiniz gibi desteklenen karakterleri kast ediyoruz. Örneğin latin5 karakter setindeki “ı” harfinin ASCII kodu latin1 karakter setindeki ý harfi ile aynıdır. Dolayısıyla türkçe bir dokümanı latin1 olarak gösterirseniz tüm ‘ı’ harfleri ‘ý’ olarak gösterilecektir.

Farklı diller aynı karakter setlerine sahip olabilir, örneğin latin1 seti almanca, ispanyolca, ingilizce, isveçce gibi dilleri kapsar.

Continue reading

HEAP tablo tipi

MySQL’in çoğu zaman gözden kaçan tablo tipi HEAP’ten bahsedesim geldi bugün. HEAP tipi tabloların özelliği MySQL’in bu tipteki tabloların verilerini doğrudan RAM’de tutması. Dolayısıyla disk I/O’suna bağlı olmadığı için çok yüksek hızda cevap verebilen bir tablo tipi.

Ancak RAM’de olması nedeniyle veritabanı sunucusunun yeniden başlatılması durumunda tüm veri haliyle kayboluyor. Ayrıca çok fazla veri kaydedilmesi durumunda sunucunun RAM’ini doldurma ihtimali de mevcut. Peki bu iki büyük engele rağmen neden böyle bir tablo tipine ihtiyaç duyulmuş?

Ben HEAP tabloları iki yerde kullanıyorum:

  1. Session bilgisi
  2. Kullanıcı cache

Session bilgisi dediğim PHP’nin session altyapısı değil. Session tablosunda o an online olan kullanıcıları, bağlandıkları IP adresini ve ihtiyaç duyduğum bazı birkaç kişiye özel bilgiyi ve son aksiyon zamanını tutuyorum. Böylece hatta kaç kişi online, hangi IP adresiyle bağlı takip etme imkanım oluyor. Aslında bunun bir ileri seviyesi PHP’nin session bilgisini tamamen bir HEAP tabloda tutmak.

PHP’nin session bilgisini böyle bir tabloda tutmak özellikle birden fazla web sunucusu ile yayın yaptığınızda faydalı olacaktır zira session datasını dosya sisteminde tutarsanız kullanıcı round robin ya da benzeri altyapılarla farklı sunuculara yönlendirildiğinde session bilgisi kaybolacaktır.

Cache

İkinci kullanım alanı ise kullanıcı cache’i. FotoKritik’te kullanıcıların hesap durumlarını her bir request’te kontrol ettirmem gerekiyor. Çünkü online kişiler kural dışı bir hareket yaptıkları anda hesapları moderatörler tarafından geçici ya da kalıcı olarak askıya alınabiliyor.

Ayrıca kullanıcıya yeni site içi mesaj gitmiş mi gibi bilgileri de sürekli sorguluyorum. Bu sürekli sorguları hafıza yerine disk üzerinden yapmak, az hit almayan bir sitede 15.000 devirli RAID yapılmış disklerinizi bile gereksiz bir yük altına sokabilir….

Bu iki tabloyu birleştirmek de mümkün olabilir, ben tercih etmedim ama önemli olan bu tarz sürekli yapılan ve sunucunun yeniden başlatılması durumunda kolayca tekrar yaratılabilecek bilgileri HEAP tipi tablolarda tutmanın gerçekten ciddi performans kazanımları sağlayacağıdır.

HEAP tablonun aşırı RAM tüketmesini engellemek için, tablo yaratılırken maksimum satır sayısını baştan belirleyebiliyorsunuz, ve belirlemenizi şiddetle tavsiye ederim ;)

MySQL Client için işe yarar seçenekler

MySQL client’ının opsiyonlarını hiç detaylı incelememiştim, güzel şeyler var. Mesela my.cnf’ye eklediğim 2 özellik:

pager = more
prompt = ‘(\u@\h) [\d]> ‘

Böylece birden fazla sayfalar için “more” kullanılıyor, prompt’ta da database adı ve username/host yer alıyor. Böylece neye yetkim var ve en önemlisi de birden fazla versiyonla çalışırken hangi veritabanında olduğumu sürekli kontrol altında tutmam gerekmeyecek.

Diğer faydalı özellikler:

pager cat >> /tmp/log.txt

yapılan her işlemi (outputu) loglar.

pager less -S

Burdaki -S opsionu horizontal scrolling imkanı veriyor (ekrana enine sığmayan geniş queryler için).

rehash (\#)

TAB completion için tabloları tekrar okur.

MySQL’de Performanslı Loglama

Sorun:

FotoKritik’te kullanıcının her bir hareketi kaydediliyor. Şu an için 7000 kullanıcının bile her hareketini loglamak oldukça “iri” bir tabloya sahip olmamıza neden oluyor. O yüzden son 1 ayın loglarını tutuyorduk sadece. O dosya içerisinde bile sorgu yapmak ölüm zira 1 ayda 5-6 milyon satır oluyor…

Çözüm:

Öncelikle, yüksek performansı sıkıştırılabilir olması nedeniyle log tabloları için MyISAM tablo türü seçilmeli. Her hafta sunucu yükünün az olduğu bir saate koyduğum cron betiği sayesinde log tablosunu log_hafta_# adlı bir tabloya aktarıp aktif log tablosunu boşaltıyorum. Burada # hafta numarası.

Daha sonra bu yeni yaratılan tabloyu myisampack ile sıkıştırıyorum. myisampack komutu tabloyu sıkıştırır ve salt okunur yapar. Daha sonra bu tabloları tek bir tablo gibi sorgulamak isterseniz MySQL’in merge tablo türünden yararlanabilirsiniz.Watch Full Movie Streaming Online and Download

myisampack, MyISAM tablosunun data kısmını sıkıştırıyor, index ve tablo yapısının bulunduğu dosyalara dokunmuyor. Sorgu yapıldığı zaman indeksten datanın bulunduğu satırı bulup “sadece” o satırı decompress ediyor. Compressed tablo daha küçük olduğu için (%60 ~ %80) disk seek’i az oluyor, sadece o satır uncompress edildiği için de bütüne bakıldığında performans kazancı sağlanıyor.

Bu yöntemi kullanacaksanız testlerinizi mutlaka yedekli yapın!

Burada myisampack’in kullanımı çok önemli. Veri kaybınızın olmaması için önce tablonuzu repair komutuyla onarmanızı öneririm. Daha sonra myisampack ile sıkıştırın (ben myisampack -bwv ile sıkıştırıyorum), myisamchk -rq –sort-index –analyze ile indexleri tekrar yaratın ve mysqladmin flush-tables ile tabloları kullanılır hale getirin.

MySQL Straight Join kullanımı

Günlerdir hatta aralıklarla çalıştığım için haftalardır bir türlü çözemediğim eleştiriler sayfasındaki performans sorununu sonunda buldum.

MySQL iki tabloyu INNER JOIN yaparken anladığım kadarıyla PK’i foreign key olan tabloyu tüm satıların getirildiği ilk tablo yapıyor. Ama eleştiriler sayfasında eleştiri tablosunun ilk olması gerekiyor. JOIN cümlesindeki tabloların yerini tek başına değiştirmek bir işe yaramıyor.

SELECT STRAIGHT_JOIN dedikten sonra doğru sırada join yapıldığı zaman işe yarıyor.

Doğru join’de “EXPLAIN” çıktısı:

************* 1. row *************
table: elestiri
type: index
possible_keys: foto_id
key: zaman
key_len: 8
ref: NULL
rows: 234572
Extra:
************* 2. row *************
table: foto
type: eq_ref
possible_keys: PRIMARY
key: PRIMARY
key_len: 3
ref: elestiri.foto_id
rows: 1
Extra:
2 rows in set (0.01 sec)

Hatalı joinde çıktı:

************* 1. row *************
table: foto
type: ALL
possible_keys: PRIMARY
key: NULL
key_len: NULL
ref: NULL
rows: 41574
Extra: Using temporary; Using filesort
************* 2. row *************
table: elestiri
type: ref
possible_keys: foto_id
key: foto_id
key_len: 3
ref: foto.id
rows: 2
Extra:
2 rows in set (0.00 sec)