Hey adamım, bunu sen istedin.
Yarım saatte küçük bir demo yaptım localhost'ta, aşağı yukarı aynı sonuçları aldım.
Önce işi parçalara bölelim, adım adım gidelim. Yenile tuşuna abandım, hemen yeni entryler gelmedi. Demek ki her birkaç dakikada bir bu kısım yenilenerek yeni bir önbellek (cache) oluşturuluyor, böylece X dakikada TEK bir sorgu yapılarak veritabanına yük binmesi engelleniyor. Birisi ekşiye her girdiğinde o kişi için özel sorgu yapılmıyor yani sol kısım için.
Mantıklı.
Sayfa başı entry benim hesapta 25, demek ki ben giriş yaptığımda bana 25 entry gösterilecek. Ekşisözlük bunu nereden biliyor? Çünkü çerez var bilgisayarımda. Vay arkadaş, bi kamyon çerez varmış.
Direk SQL sorgusu ile yazarsak uzun sürer, verimsiz olur ve güvenli olmaz, ORM kullanarak yapıyorum ben bu işleri, sana da öyle yapmanı tavsiye ederim. Algoritma demişsin, yol yordam demişsin, ben de onu anlatıyorum aşağıda.
Tablo yapısını basitçe kuralım önce. Elimizde başlık, kullanıcı ve giriş isminde üç tablo olması lazım. Bunları jargona uydurmak için İngilizce yazacağım.
users -> kullanıcı tablosu
entries -> entry tablosu
topics -> başlık tablosu
Önce veritabanı ilişkilerini kuralım.
Bir kullanıcı birden fazla başlığa sahip olabilir.
Bir kullanıcı birden fazla entry'e sahip olabilir.
Bir başlığa birden fazla entry girilebilir.
Şimdi geldik en cafcaflı yerine. Kullandığın ORM'e göre değişmekle beraber -gerçi hepsinde aynı şeyler var-, kuracağın ilişkiler şöyle olacak.
user -> hasMany topics -> bir kullanıcının tüm başlıkları -> 1-çok ilişki
topic -> belongsTo user -> bir başlığın sahbi olan kullanıcı -> 1-1 ilişki
user -> hasMany entries -> bir kullanıcının tüm entryleri -> 1-çok ilişki
topic -> hasMany entries -> bir başlığın tüm entryleri -> 1-çok ilişki
entry -> belongsTo user -> bir entry'i yazan kullanıcı -> 1-1 ilişki
entry -> belongsTo topic -> bir entry'nin ait olduğu başlık -> 1-1 ilişki
Eğer bir kullanıcının karşı tabloda yalnızca bir kayıtla ilişkisi olsaydı o zaman hasMany yerine hasOne yapacaktık ama şuanda hasOne yapacak bir durum mevcut değil. Çok nadir kullanılan bir ilişki tipi bu.
Basitçe bir şema hazırlayacak olursak
Tüm id'ler int(11) ve auto_increment olacak
users
-id
-username
-email
-created_at
-updated_at
-password_hash
topics
-id
-name
-user_id -> users tablosundan foreign key olarak ekliyoruz başlığa ukteyi kim verdi? yani kim açtı? (sözlük nasıl işliyor bilmiyorum, sanırım ukte deniyordu adına)
-today_entry_count
-created_at
-updated_at
entries
-id
-entry -> içerik
-topic_id -> topics tablosundan foreign key olarak ekliyoruz. (bu entry hangi başlığa ait?)
-user_id -> users tablosundan foreign key olarak ekliyoruz. (bu entry'i kim yazdı?)
-created_at -> ne zaman yazdı?
-updated_at -> ne zaman düzenledi?
-is_visible -> 0 ya da 1 (entry görünür durumda mı?)
Bugünü mü göstereceksin?
Topics tablosuna git.
Tüm başlıkları seç.
En son güncellenen 25 başlığı bul.
En yeniden en eskiye göre sırala.
Başlıkları döndür.
Bitti.
Gündemi mi göstereceksin?
Topics tablosuna git.
İçinde today_entry_count var, her entry girildiğinde bir artıyor orası. Gece 12'de de cronjob veya mysql trigger ile siliniyor.
Son 24 saat içinde en az 50 entry almış tüm başlıkları seç.
25 ile limitle.
En yeniden en eskiye göre döndür.
Bitti.
Video eklemek istersen yine aynı, bir başlığın bir videosu var hep.
Bu kısım nispeten kolay ama işin içine kanalları katarsan o zaman bire çok ve bire bir ilişkiler yetmez, çoka çok ilişki lazım. belongsToMany yani.
Niye?
5 tane kanal olsun.
1 tane başlık olsun.
Bu başlığın ve üç kanalı olsun.
Eğer başlığın birden fazla kanalı olacaksa -yani şu durumdaki gibi- (bir başlık birden fazla kanala aitken bir kanal da birden fazla başlığa ait, burası önemli) hem başlık tablosuna channel_1, channel_2 diye yeni sütun eklemek saçma olacaktır hem de bir kanala ait başlıkları getirmek için kanal tablosuna topic_1, topic_2 diye onlarca, hatta binlerce sütun açmamız gerekecek.
O yüzden çoka çok ilişki kuruyoruz, belongsToMany.
channel_topic diye bir tablo oluşturuyorum.
id
channel_id -> channels tablosundan foreign key
topic_id -> topics tablosundan foreign key
channels ve topics tablolarına şu ilişkileri kuruyoruz.
channels -> belongsToMany topics
topics -> belongsToMany channels
Niye iki tane ayrı ilişki kurdum? Üstteki bir kanalın tüm başlıklarını almaya yararken alttaki bir başlığın tüm kanallarını almaya yarıyor. Tablo ilişkisinin tersini de ayarlaman lazım ki veritabanındaki diğer kayıtları da alabilesin.
Ekşisözlüğün veritabanı ne kadar büyük bilmiyorum ama arşivleme ve yük getirmeyen kısımlar için MySQL, aktif kısımlar içinse Redis kullanmak daha yüksek performans sağlar diye düşünüyorum.
0