Mysql (100 एम पंक्ति पंक्ति से अधिक) में अपठित आलेख प्राप्त करने के लिए डेटाबेस डिज़ाइन - mysql, sql, डेटाबेस, डेटाबेस-डिज़ाइन, मारियाडब

यह जानकारी बहुत सघन है।

2 टेबल हैं।

लेख

-----------------------------------
|id | weight | text               |
-----------------------------------
|1  | 10     | blah               |
|2  | 100    | blah               |
|3  | 50     | blah               |
|4  | 1000   | blah               |
-----------------------------------

पढ़ना

-----------------------------------
| user_id | article_id            |
-----------------------------------
| 1       | 4                     |
| 1       | 2                     |
| 1       | 3                     |
| 2       | 3                     |
| 2       | 4                     |
-----------------------------------

मैं नीचे क्वेरी (बहुत संघनित) का उपयोग करके अपठित लेख प्राप्त करना चाहता हूं

SELECT
a.*
FROM
article a LEFT OUTER JOIN read r ON r.article_id = a.id and r.user_id = 1
WHERE
r.id IS NULL
ORDER BY
a.weight DESC
LIMIT 10

महत्वपूर्ण जानकारी

  1. की संख्या read table पंक्तियाँ प्रति उपयोगकर्ता 1000 से नीचे रहती हैं। (पुराने डेटा को हटा दें)
  2. लेख तालिका में भार स्तंभ अक्सर बदला जाता है। (इसका मतलब है आदेश तय नहीं)

समस्या है .. (जब उपयोगकर्ताओं की संख्या: 1M से अधिक)

  1. पढ़ने की मेज का उपयोग करते हुए अपठित लेख प्राप्त करने का तरीका (नहीं, बाहरी जुड़ाव महत्वपूर्ण नहीं है)
    • की संख्या read table पंक्तियाँ 1G से अधिक होंगी

यह अब तक अच्छी तरह से काम करता है (पढ़ने की तालिका पंक्तियों का वर्तमान #: 100M) लेकिन मुझे अगला कदम तैयार करना होगा क्योंकि उपयोगकर्ताओं की संख्या तेजी से बढ़ रही है।

इस मामले में बड़ी सेवा के लिए सबसे अच्छा तरीका क्या है?

(पैनापन? विभाजन तालिका; या फिर नया स्वरूप?)

अग्रिम में धन्यवाद

उत्तर:

जवाब के लिए 0 № 1

बिंदु, जहां तक ​​संभव हो सूचकांक का उपयोग करना है।

SELECT a.*
FROM  a
LEFT JOIN read r
ON r.article_id = a.id and r.user_id =1
WHERE r.id IS NULL
ORDER BY a.weight DESC
LIMIT 10

संपादित करें: आपके लिए चिंता का डेटा आकार है read तालिका और हमें डेटा का आकार कम करना होगा। उसके लिए हमारे पास कई विकल्प हैं:

  • MySQL विभाजन: user_id की सीमा पर विभाजन बनाते हैं (प्रति विभाजन 100K उपयोगकर्ता हो सकते हैं
  • कई टेबल बनाएं: विभाजन के समान, लेकिन आपके पास अलग-अलग डेटाबेस (यहां तक ​​कि अलग-अलग डीबी सर्वर में) डेटा होगा। User_id के आधार पर, आप शामिल होने के लिए तालिका / डेटाबेस पर निर्णय लेंगे।

इसके अलावा, आप समय-समय पर पुराने डेटा के अभिलेखीय होने के बारे में सोच सकते हैं और यह तय करने के लिए एप्लिकेशन को स्मार्ट होना चाहिए कि उसे संग्रहीत तालिका या लाइव टेबल को क्वेरी करने की आवश्यकता है या नहीं।


जवाब के लिए 0 № 2
  • इसमें एक कॉलम जोड़ें article। यह एक ध्वज होगा जिसमें कहा जाएगा कि क्या लेख पढ़ा / पढ़ा नहीं गया है। (इसे उपयोगकर्ता की गिनती या टाइमस्टैम्प न बनाएं; यह बाद के चरणों को धीमा कर देगा।)
  • जब भी कोई उपयोगकर्ता एक लेख पढ़ता है, तो ध्वज की जांच करें और यदि आवश्यक हो तो इसे बदल दें।
  • है 'INDEX (झंडा, वजन, आईडी) - यह आपकी क्वेरी को लगभग तुरंत चलने देगा। यह उस मिलियन-पंक्ति तालिका पर ठीक होना चाहिए।

एक समस्या:चूँकि आप शुद्ध कर रहे हैं (1000 के बाद), कुछ "पढ़े" लेख "अपठित" बन सकते हैं। इससे निपटने के लिए, पर्सिंग को बैच दें, और उन लेखों की अलग सूची इकट्ठा करें जो शुद्ध हो गए। फिर झंडे को फिर से गणना करने का थकाऊ कार्य करें, लेकिन सिर्फ उन लेखों के लिए। INDEX(article_id) मदद करेगा; उपयोग EXISTS ( SELECT * FROM read WHERE article_id = $aid )। (यह एक बार में एक सहायता के बजाय शायद एक बैच ऑपरेशन में बदल सकता है।

एक और समस्या: अरब-पंक्ति तालिकाओं पर द्वितीयक कुंजियाँ महंगी हैं - वे बहुत सारे I / O को जन्म दे सकती हैं। इस समस्या को दूर करने का प्रयास करने से पहले, कृपया प्रदान करें SHOW CREATE TABLE दोनों तालिकाओं के लिए, किसी भी अन्य सामान्य के लिए SELECTs। सही सूचकांक (तों) और डेटाटिप्स चुनना है बहुत अरब-पंक्ति तालिकाओं में प्रदर्शन के लिए महत्वपूर्ण ..


संबंधित सवाल
सबसे लोकप्रिय