वहाँ एक और है।
एक पदानुक्रमित मंच संरचना (बोर्ड> अनुभाग> धागा, आदि) के लिए विस्तृत पढ़ने/अपठित डेटा स्टोर करने का एक और तरीका। यह बिना किसी के करता है) पढ़ने/अपठित जानकारी को पूर्व-पॉप्युलेट करना है, और बी) अपने सबसे खराब मामले में यू * (एम/2) पंक्तियों से अधिक स्टोर किए बिना, जहां यू उपयोगकर्ताओं की संख्या है, और एम है डेटाबेस में पोस्ट की कुल संख्या (और आमतौर पर बहुत अधिक, इससे कम)
मैंने कुछ समय पहले इस विषय पर शोध किया था। मैंने पाया कि एसएमएफ/पीएचबीबीबी "धोखा" थोड़ा सा है कि वे उपयोगकर्ता पढ़ने के इतिहास को कैसे स्टोर करते हैं।उनकी स्कीमा किसी भी दिए गए बोर्ड, फोरम, सबफोरम, विषय (या सीधे ब्राउज़र द्वारा देखी गई) में पढ़ने के रूप में चिह्नित की गई अंतिम टाइमस्टैम्प या संदेश आईडी का भंडारण का समर्थन करती है, जैसे:
[user_id, board, last_msg_id, last_timestamp]
[user_id, बोर्ड, मंच, last_msg_id, last_timestamp]
[user_id, बोर्ड, मंच, subforum, last_msg_id, last_timestamp]
[user_id, बोर्ड, मंच, subforum, विषय, last_msg_id , last_timestamp]
इससे उपयोगकर्ता विशिष्ट बोर्ड, मंच, विषय इत्यादि को "पढ़ा" के रूप में चिह्नित कर सकते हैं। हालांकि, उपयोगकर्ता के हिस्से (या तो पढ़कर, या सक्रिय रूप से "पढ़ने के रूप में चिह्नित" पर क्लिक करके) की आवश्यकता होती है, और phpBB के मामले में, आपको यह कहने के लिए ग्रैन्युलरिटी नहीं दी जाती है "मैंने यह विशिष्ट देखा है संदेश, लेकिन वह विशिष्ट संदेश नहीं। " आपको वह स्थिति भी मिलती है जहां आपने पहले किसी विषय में अंतिम संदेश पढ़ा था (थ्रेड में नवीनतम गतिविधि देखना), और आपको तुरंत बाकी धागे को पढ़ने के लिए माना जाता है।
यह ऐसी चीजों को स्टोर करने के लिए एसएमएफ और पीएचबीबी के लिए काम करता है क्योंकि यह दुर्लभ है कि आप कभी भी एक पोस्ट देख रहे हैं (किसी विषय के अंतिम पृष्ठ में 20+ पोस्ट के लिए डिफ़ॉल्ट दृश्य सेट अप किए गए हैं)। हालांकि, अधिक थ्रेडेड मंचों के लिए (विशेष रूप से मंच जहां आप एक समय में संदेश देख रहे हैं), यह आदर्श से कम है। इस प्रणाली के उपयोगकर्ता शायद एक बहुत कुछ परवाह करेंगे यदि उन्होंने एक संदेश पढ़ा है लेकिन कोई दूसरा नहीं है, और शायद इसे पूरे अनुभाग को पढ़ने के रूप में चिह्नित करने में सक्षम हो, जब वास्तव में वे केवल कुछ को पढ़ने के रूप में चिह्नित करना चाहते थे।
आप इस तरह tuples में संदेशों को संग्रहीत: [user_id, lower_msg_id, upper_msg_id]
उपयोगकर्ता इतिहास लॉग के रूप में बनाए रखा है निम्नलिखित:
पृष्ठ दृश्य पर, एक समारोह अगर user_id एक को देखने के लिए लग रहा है रिकॉर्ड करें जहां current_msg_id low_msg_id और upper_msg_id के बीच है। यदि यह है, तो यह पृष्ठ पढ़ा जाता है, और कोई कार्रवाई की आवश्यकता नहीं है। यदि ऐसा नहीं है, तो एक और क्वेरी जारी की जानी चाहिए, इस बार यह निर्धारित करना है कि current_msg_id या तो low_msg_id (current_msg_id == lower_msg_id-1) से कम है, या upper_msg_id (current_msg_id == upper_msg_id +1) से अधिक है। यह वह मामला है जहां हम अपनी "पढ़ी" या "देखी गई" सीमा को 1 तक बढ़ाते हैं। यदि हम low_msg_id या uppper_msg_id से दूर हैं, तो हम उस दिशा में 1 तक टुपल बढ़ाते हैं। अगर हम अपनी ट्यूपल रेंज नहीं बढ़ा रहे हैं, तो हम एक नया टुपल, [user_id, current_msg_id, current_msg_id] डालते हैं।
कॉर्नर केस तब होता है जब दो ट्यूपल श्रेणियां एक दूसरे से संपर्क करती हैं। इस मामले में, निचले ट्यूपल सीमा और ऊपरी ट्यूपल सीमा के बीच खोज करने पर, निचले टुपल की ऊपरी सीमा को ऊपरी टुपल की ऊपरी सीमा तक सेट करके दो ऊपरी सीमाओं को मर्ज करें, और ऊपरी ट्यूपल को हटा दें। PHP में
कोड उदाहरण: जहां current_msg_id किसी भी lower_msg_id के बीच मौजूद नहीं है तथा उसे किसी उपयोगकर्ता के लिए upper_msg_id (एक नहीं एसक्यूएल मामले में क्वेरी मौजूद है)
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.
}
}
अपठित पोस्ट के लिए खोज हो रही है। एक संबंधपरक डेटाबेस में कार्यान्वित करते समय यह सबसे कुशल प्रश्न नहीं है, लेकिन आक्रामक अनुक्रमण द्वारा हल किया जा सकता है। उदाहरण के लिए, निम्न, किसी उपयोगकर्ता अपठित पोस्ट की गणना के लिए एक SQL क्वेरी है चर्चा क्षेत्र ("आइटम") द्वारा समूहीकरण कि पदों में हैं:
$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
;
अधिक उपयोगकर्ताओं को मंच पर पढ़ा, प्रत्येक ट्यूपल द्वारा पढ़ने के रूप में चिह्नित सीमाओं को व्यापक करें, और कम tuples को संग्रहीत किया जाना चाहिए। उपयोगकर्ताओं को पढ़ने बनाम सटीक गिनती मिल सकती है।अपठित, और प्रत्येक फोरम, सबफोरम, विषय इत्यादि में पढ़ने बनाम अपठित देखने के लिए आसानी से समेकित किया जा सकता है
2000+ पदों के एक छोटे से मंच को देखते हुए, निम्नलिखित संग्रहित tuples की संख्या के बारे में उपयोग आंकड़े हैं , उपयोगकर्ताओं द्वारा लॉग इन किए गए कई बार क्रमबद्ध (उपयोगकर्ता गतिविधि अनुमानित)। कॉलम "num_bounds" उपयोगकर्ता के "num_posts_read" देखने के इतिहास को संग्रहीत करने के लिए आवश्यक टुपल्स की संख्या है।
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
मैं किसी भी मंच पर इस विशेष कार्यान्वयन लेकिन मेरे स्वयं के कस्टम एक नहीं देखा है, और यह कि एक छोटा सा एक है। मुझे दिलचस्पी होगी अगर किसी और ने लागू किया है, या इसे कहीं और लागू किया है, खासकर बड़े और/या सक्रिय मंच में।
सादर,
Kaiden
मुझे अभी भी लगता है कि ऐसा करने का एक आसान तरीका होना चाहिए। मैंने MemCache का उपयोग करने के बारे में सोचा, लेकिन यह स्मृति पर निर्भर करता है, और मैं अभी भी एपीसी के बारे में सोच रहा हूं। अगर मेरे पास काम करने के लिए कुछ प्रकार की कैश फ़ाइल हो सकती है, तो शायद मदद मिलेगी। – yoda