@aib MySQL’e “dandik” diyip duruyor, neden? Hakkaten kullanmamali miyim? Yerine ne kullanabilirim?
Not: MySQL ile son temasim ve son buyuk basagrim 10 sene kadar once idi. Bir kismi simdiye kadar duzelmis olabilir ama ayni kalmissa sasirmam; o noktada “yeni” sayilmazdi.
MySQL, database’lerin temeli olarak bilinen ACID prensiplerini “olursa iyi olur” diye alan bir sistem. Cogunun patladigi ornegi asagilarda okuyabilirsiniz.
SQL standardini da “benzesek fena olmaz” diye kullanan bir sistem. En buyuk sapmalari da asagida olacak…
“Ogrenmek icin” kullanmakta bir sakinca yok fakat PostgreSQL’e tercih edilecegi bir durum dusunemiyorum. Kurulum kolayligi? Cesitlilik?
Production’da filan kullanirsaniz “tablo [az milyon] row’da patlamaya basladi, query yapamiyoruz, kolon bile silemiyoruz” diye gelmeyin. “Facebook kullaniyormus” diye de gelmeyin; Facebook’a gidin.
PostgreSQL. Bu arada su dokumentasyon baska database kullanirken bile ise yariyor.
Tek program icin data tutuyorsan SQLite bolgesine yakinsin. “Database” demeye bin sahit istemekle beraber kendi alaninda cok iyi oldugu icin bahsedeyim dedim.
Veya SQL kullanmamayi dusundun mu? Dilinin serialization kutuphaneleri cok daha kolay olabilir.
2010’da sozluge yazdigim bir entry var. Oldugu gibi atiyorum:
bas agrilari:
boolean
kolon turu yoktur. “bool
” kolon tur ismitinyint
(1)'e alias’lidir. insanlaritrue
/false
yerine 1/0 insert etmeye itmesi bile yeter.otomatik artan (bkz: auto-increment) kolon turu yoktur.
enum
kolonlarina enum’da olmayan bir deger insert etmenize izin verir ve yaptiginizda bambaska bir deger (‘’) insert eder.
enum
kolonlarindaenum
’da olmayan bir deger (‘’) saklamaniza izin verir.
ansi
standart quote’lari opsiyoneldir ve default kapali gelir. export tool’lari,ansi
standart quote’lari kullanan script’ler uretemez.
drop table
,truncate table
;rollback
edilebilmeyi birakin, o anki transaction’icommit
eder.constraint check’leri defer edilemez.
fk
’li iki rowu birbirine bagladiktan sonra silmeye calisip eglenebilirsiniz. (ipucu:on delete
)yanlis
date
/datetime
expression’larini 0000-00-00 [00:00:00]'a cevirir.saniyenin altinda granularitede tarih/saat tutamaz.
her turlu
index
operasyonu icin butun tabloyu, gecici bir tabloya kopyalayip geri almak sureti ile bastan yaratir. (gecici tablo limiti asarsa disk tablosuna duser)|| operatorunu
or
operatoru zanneder.
text
,binary
data ve hattainteger
’lar icin degisik bir suru kolon tipleri vardir.text
mi yoksamediumtext
mi kullanmaliyim diye dusunup durursunuz.
regexp
destegi match’ten ibarettir. (capture yok, replace yok)
union
kullananview
’larda index propogasyonu yapamaz, onceview
’i gecici bir tabloda materyalize edip, sonra filtrelemek sureti ile sonuc dondurur. (gecici tablo limiti asarsa disk tablosuna duser)query planner’i
limit
’li query’leri pek iyi optimize edemez,row
’lariorder
’a gore getirip filtre uygulamanin cok daha hizli olacagi durumlari es gecip filtrelemeyi once yapabilir. (http://www.mysqlperformanceblog.com/2010/03/18/when-the-subselect-runs-faster/)query’lerde tablo basina tek
index
kullanmayi cok sever.explain
ciktisinda bile “kullanilan index” yazar. insanlarda “where
clause’unda ne kadar kolon kullaniyorsan hepsini ayni sirada birlestiren bir multi-kolon index yaratmalisin” gibi yanlis dusuncelerin dogmasina neden olur.
null
olamayan ve default degeri olmayan kolonlara kafasina gore default deger verir.
ansi
standartcomment
sekansini (“–”) tanimaz.query planner’i, 3-5 id donduren subselect uzerinden diger kolonlari secen bir query kullandiginizda, her seyin gecici bir tabloya atilmasina; full tabloyu saniyenin altinda scan eden aletin disk access yapacagim diye dakikalarca debelenmesine neden olabilir. “select * from tablo where id in (select id from tablo where …)” gibi bir query’i elle optimize etmek zorunda kalirsiniz: ic query’i calistirir, sonuclari alir, aralarina virgul koyup where in ()'e atarsiniz. virgulleri tek tek elle koydugunuz halde bile orijinal query’den daha hizli (milisaniye vs. dakikalar) sonuc alirsiniz.
yine subselect’lerle ilgili ama yukaridakinden bagimsiz olarak, 0 sonuc donduren bir ic query’e ragmen toplam query’nin 10 saniye surdugu gorulmustur. tekrarlayalim; ic query: 0 result, dis query: haliyle 0 result, running time: 10.0xx saniye. bu durum ic query’nin dondurdugu row sayisina gore degisir: 0, 1, 3 ve 99 row donduren ic query’i kullanip ayni sayida row donduren query’lerin 10.0xx saniye; 2, 4, 5, 150 ve 384 row dondurenlerin ise milisaniyeler aldigi gozlemlenmistir. hepsi son derece supheli bir sekilde ~10 saniye suren yavas query’lerden hic data kullanmayan 0/0 row’luk olani debug modu acik calistirilip bi yandan da source koddan takip edildiginde ise edinilen sonuc sudur: innodb, 0’ar byte’lik data paketleri ‘yollayan’ bir “sending data” sonsuz loop’una girmistir. 10 saniye ise kendisine verilen timeout suresidir.
tek kolonlu bos
innodb
tablosuna iki thread’deninsert
yaparsanizdeadlock
olabilirler!! (http://bugs.mysql.com/bug.php?id=51140#c282323)
ya abi, yok… ben bosuna ugrasiyorum. bu… yani… yazi yazma yetenegimi kaybettim. sunun uzerine ne diyebilirim ki? ne desem fayda edecek ki?[eklemiycem baska bisiy, yeter be]
“select *, count(*) […]” gibi bir query’e izin verirken “select count(*), * […]” gibi bir query’e izin vermez.
gruplu query’lerde gruplanmamis kolonlari secmenize izin verir: “select a, b […] group by a” (gerci ne yalan soyliyim, elle query yaparken “select * […] group by a” diyip ful sema arti her kolondan birer ornek gormeyi seviyorum.)
gruplu query’lerde gruplanmamis kolonlari secerseniz butun degerlerine tek tek bakip herhangi birini dondurmek icin table scan’e duser. (ama ender durumlarda index kullanabileceginden supheleniyorum)
where
analizi “(x is null or x is not null)” gibi bir clause’un her zaman true olacagini bilemez (ve index fail’leriyle beraber (#16) muhtemelen table scan’e dusurur)
where
clause’lari icin schema analizi yapamaz; not null kolona “(x is null)” gibi bir kosul verdiginizde dahi tum tabloyu tarar. (aslinda index taramasi lazim, ama bakiniz yukarisi, #16.)tablolari sadece nested loop ile join edebilir! (soldaki her row icin: sagdaki karsiligi bul) oha oha oha - ben de niye denormalizasyon hastasi diyordum insanlar.
advisory lock
vardir ama baglanti basina bir tane alinabilir. (ikincisi alinirsa ilki otomatikmen unlock edilir)paralelizasyonu felakettir; tutup 32 cpu’lu makinaya kurarsaniz 28’i ile protein katlayabileceginizi fark edersiniz.
explain
sadece select’lerde calisir.siyasiler ve daha neler neler: MySQL Gotchas
http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html adresinde dokumente edilen (5.1’i kendi versiyonunuzla degistirebilirsiniz) opsiyonlarin bir kismiyla yukaridaki basagrilarinin bir kismini duzeltebilir, veya manyaksaniz daha fazlasini bulabilirsiniz.
ahahahahah
ahahahahaa
ahahaaahahahaa
utf-8
desteklemiyormus. gidin bakin siz de gulun: http://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8.html (edit: 5.5’te gelmis)
Veritabanları gereksizdir. Büyük şirketler bütün bilgilerini asdf.csv diye bir dosya açıp, araya virgül koya koya oraya yazarlar.
@aib hocanın sinirlerini bozduğuma göre gidebilirim…
Ah evet cok iyi dedin. Gordugum database kullanan cogu sistem, bir text dosyasi, bir CSV, bir JSON veya en azindan SQLite kullansa, daha hizli bir surede, daha az basagrisiyla ve daha hizli calisacak sekilde yazilabilirdi.
Ozellikle burada, login datasi filan tutan insanlara dict
pickle
etseydin dememek icin kendimi zor tutuyorum, yeri geldiginde diyorum. Tabi ki yine “ogrenmek icin” kullanilmasina karsi degilim.
“Rule of thumb”: En az bir foreign key constraint’iniz olmayacaksa SQL buyuk ihtimalle overkill yani gereksiz.
Bu benim de hiç düşünmediğim bir şeydi, öğrendiğim iyi oldu.
Kendi sorusunu kendi cevaplayan aib: