Orada ... başka.
Hiyerarşik bir forum yapısı (yönetim kurulu> bölüm> iplik, vb) için ayrıntılı okundu / okunmadı verileri saklamak için başka bir yolu. O olmadan yapar a) önceden doldurmak / okunmamış bilgileri okumak ve b) her zamankinden daha fazla saklamak zorunda kalmadan sahip daha U * U kullanıcı sayısı, ve M onun kötü durumda, (M / 2) satır toplam veritabanında mesajların sayısı (ve genellikle çok, bu çok daha az)
Ben bir süre önce bu konuyu araştırdım. Ben SMF / phpBB onlar kullanıcı okuma geçmişini saklamak nasıl biraz "hile" olduğunu buldu. Onların şema son damgaları veya belirli bir yönetim kurulu okundu olarak işaretlenmiş mesaj kimliği ya da depolanmasını destekler, forum, subforum, konu (ya da tarayıcı tarafından doğrudan izlendi) şöyle:
[User_id, tahta, last_msg_id, last_timestamp]
[User_id, tahta, forum, last_msg_id, last_timestamp]
[User_id, tahta, forum, subforum, last_msg_id, last_timestamp]
[User_id, tahta, forum, subforum, konu, last_msg_id, last_timestamp]
Bu "okuma" olarak kullanıcılar, vb gibi belirli panoları, forumlar, konular işareti sağlar. Bu gerektirir, ancak, (okuma, ya da aktif "okundu olarak işaretini" linkine tıklayarak ya) ve phpBB durumunda kullanıcı adına eylem, ya sen "Ben bu özel gördük demek için zerreliğini vermez mesajı, ancak belirli değil mesajı. " Ayrıca, (bir iplik son etkinliği görüntüleme) ilk konudaki son mesajı okumak ve hemen iplik kalanını okudum kabul ediyoruz durum olsun.
Bu şimdiye kadar tek bir yazı (Varsayılan görünümleri bir konunun son sayfasında 20 + mesaj için ayarlanmıştır) inceliyorsunuz nadir çünkü bu gibi şeyleri saklamak için SMF ve phpBB için çalışıyor. Ancak, daha dişli forumlarda (iletilere bir anda görüntülemekte olduğunuz özellikle forumlar) için, bu ideal daha azdır. Bu sistemin Kullanıcılar, bir mesaj okudu ama başka varsa büyük olasılıkla bir sürü bakım, ve sadece gerçekten onlar sadece istediği okundu olarak tüm bir bölümü, işaretlemek mümkün hantal düşünebilirsiniz okundu olarak işaretlenmiş bir kaç.
Böyle dizilerini mesajları saklamak: [User_id, lower_msg_id, upper_msg_id]
Kullanıcı tarih log aşağıdaki gibi korunur:
Sayfa görünümü üzerine bir işlev User_id current_msg_id lower_msg_id ve upper_msg_id arasında bir kayıt olup olmadığını görmek için bakar. Varsa, o zaman bu sayfayı okuyun ve hiçbir eylem ihtiyaçları alınır. Değil varsa, o zaman başka bir sorgu current_msg_id (current_msg_id == lower_msg_id-1), ya da upper_msg_id daha birini (current_msg_id == 1 upper_msg_id) lower_msg_id fazla bir ya az ise bu sefer belirlenmesi, çıkarılacak vardır. Bu, büyümek böyledir bizim "okumak" ya da 1 ile sınırını "görüldü". Biz bir uzak lower_msg_id veya uppper_msg_id gelen iseniz, o zaman biz bu yönde 1 ile başlığın büyür. Bizim demet dizi büyüyen değilseniz, o zaman yeni bir başlığın takın, [User_id, current_msg_id, current_msg_id].
Iki başlığın aralıkları birbirine yaklaştığı zaman köşe durumdur. Bu durumda, alt sınır ve başlığın üst başlığın sınırı arasındaki arama üzerine, üst başlığın üst sınırına alt başlığın üst sınırını ayarlayarak iki sınırları birleştirme ve üst başlığın silin.
PHP kod örneği:
function seen_bounds( $usr_id, $msg_id ) {
# mysql escape
$usr_id = mres( $usr_id );
$msg_id = mres( $msg_id );
$seen_query = "
SELECT
msb.id,
msb.lower_msg_id,
msb.upper_msg_id
FROM
msgs_seen_bounds msb
WHERE
$msg_id BETWEEN msb.lower_msg_id AND msb.upper_msg_id AND
msb.usr_id = $usr_id
LIMIT 1;
";
# See if this post already exists within a given
# seen bound.
$seen_row = query($seen_query, ROW);
if($seen_row == 0) {
# Has not been seen, try to detect if we're "near"
# another bound (and we can grow that bound to include
# this post).
$lower_query = "
SELECT
msb.id,
msb.lower_msg_id,
msb.upper_msg_id
FROM
msgs_seen_bounds msb
WHERE
msb.upper_msg_id = ($msg_id - 1) AND
msb.usr_id = $usr_id
LIMIT 1;
";
$upper_query = "
SELECT
msb.id,
msb.lower_msg_id,
msb.upper_msg_id
FROM
msgs_seen_bounds msb
WHERE
msb.lower_msg_id = ($msg_id + 1) AND
msb.usr_id = $usr_id
LIMIT 1;
";
$lower = query($lower_query, ROW);
$upper = query($upper_query, ROW);
if( $lower == 0 && $upper == 0 ) {
# No bounds exist for or near this. We'll insert a single-ID
# bound
$saw_query = "
INSERT INTO
msgs_seen_bounds
(usr_id, lower_msg_id, upper_msg_id)
VALUES
($usr_id, $msg_id, $msg_id)
;
";
query($saw_query, NONE);
} else {
if( $lower != 0 && $upper != 0 ) {
# Found "near" bounds both on the upper
# and lower bounds.
$update_query = '
UPDATE msgs_seen_bounds
SET
upper_msg_id = ' . $upper['upper_msg_id'] . '
WHERE
msgs_seen_bounds.id = ' . $lower['id'] . '
;
';
$delete_query = '
DELETE FROM msgs_seen_bounds
WHERE
msgs_seen_bounds.id = ' . $upper['id'] . '
;
';
query($update_query, NONE);
query($delete_query, NONE);
} else {
if( $lower != 0 ) {
# Only found lower bound, update accordingly.
$update_query = '
UPDATE msgs_seen_bounds
SET
upper_msg_id = ' . $msg_id . '
WHERE
msgs_seen_bounds.id = ' . $lower['id'] . '
;
';
query($update_query, NONE);
}
if( $upper != 0 ) {
# Only found upper bound, update accordingly.
$update_query = '
UPDATE msgs_seen_bounds
SET
lower_msg_id = ' . $msg_id . '
WHERE
msgs_seen_bounds.id = ' . $upper['id'] . '
;
';
query($update_query, NONE);
}
}
}
} else {
# Do nothing, already seen.
}
}
Current_msg_id belirli bir kullanıcı (bir NOT SQL açısından sorgusu VAR) için herhangi lower_msg_id ve upper_msg_id arasında yok nerede okunmamış mesajların arıyor bulgudur. Bir ilişkisel veritabanı uygulama sorguları en verimli değil, ama agresif indeksleme ile çözülebilir. Örneğin, aşağıdaki mesaj olduğu tartışma alanı ("item") göre gruplandırma, belirli bir kullanıcı için okunmamış mesajları sayma için bir SQL sorgusu:
$count_unseen_query = "
SELECT
msgs.item as id,
count(1) as the_count
FROM msgs
WHERE
msgs.usr != " . $usr_id . " AND
msgs.state != 'deleted' AND
NOT EXISTS (
SELECT 1
FROM
msgs_seen_bounds msb
WHERE
msgs.id BETWEEN msb.lower_msg_id AND msb.upper_msg_id
AND msb.usr_id = " . $usr_id . "
)
GROUP BY msgs.item
;
Daha fazla kullanıcı foruma, geniş her demet tarafından okundu olarak işaretlenmiş sınırları, ve daha az tuplelar depolanmak zorunda okumaya. Kullanıcılar okunmamış vs okumak doğru bir sayı alabilirsiniz, ve oldukça kolay vs vs her forumda, subforum, konu okunmamış okumak görmek için toplanmış olabilir
Yaklaşık 2000 + mesaj, küçük bir forum önüne alındığında, aşağıdaki kullanıcılar (kullanıcı etkinliği yaklaşan) giriş yaptıktan kez sayısına göre sıralanır saklanan dizilerini, sayısı ile ilgili kullanım istatistikleri. Sütun "num_bounds" geçmişini görüntüleme kullanıcının "num_posts_read" saklamak için gerekli dizilerini sayısıdır.
id num_log_entries num_bounds num_posts_read num_posts
479 584 11 2161 228
118 461 6 2167 724
487 119 34 2093 199
499 97 6 2090 309
476 71 139 481 82
480 33 92 167 26
486 33 256 757 154
496 31 108 193 51
490 31 80 179 61
475 28 129 226 47
491 22 22 1207 24
502 20 100 232 65
493 14 73 141 5
489 14 12 1517 22
498 10 72 132 17
Ben bu herhangi bir forumda özel uygulamasını ama benim kendi özel biri görmedim, ve o küçük bir biri. Herkesten uygulanan, ya da bu özellikle büyük ve / veya aktif forumda, başka bir yerde hayata gördü eğer ilgi duyarım.
Selamlar,
Kaiden