मेरे पास एक ऑनलाइन गेम के लिए एक सरल उच्च स्कोर सेवा है, और यह अपेक्षा से अधिक लोकप्रिय हो गया है। उच्च स्कोर एक webservice है जो नीचे दिखाए गए एक साधारण तालिका के साथ एक MYSQL बैकएंड का उपयोग करता है। प्रत्येक उच्च स्कोर रिकॉर्ड को इस तालिका में एक पंक्ति के रूप में संग्रहीत किया जाता है। समस्या यह है कि 140k पंक्तियों के साथ, मुझे कुछ महत्वपूर्ण प्रश्नों को धीमा कर दिया जाता है कि यह जल्द ही सेवा अनुरोधों के लिए बहुत धीमा हो जाएगा।एक उच्च स्कोर डेटाबेस स्केलिंग
मुख्य तालिका इस प्रकार है:
- आईडी प्रत्येक के लिए एक अद्वितीय कुंजी स्कोर रिकॉर्ड
- खेल खेल है, जिसमें स्कोर (वर्तमान में प्रस्तुत की आईडी नंबर है, हमेशा के बराबर होता है "1" जल्द ही, हालांकि अधिक खेल का समर्थन करना होगा)
- नाम है कि खिलाड़ी के प्रस्तुत करने
- playerId के लिए प्रदर्शन नाम है
- स्कोर सांख्यिक स्कोर को प्रतिनिधित्व पूर्व 42,035 है उसे किसी उपयोगकर्ता के लिए एक अद्वितीय ID है
- समय सबमिशन समय
- रैंक एक बड़ा पूर्णांक है जो किसी दिए गए गेम के लिए स्कोर सबमिशन को विशिष्ट रूप से प्रकार देता है। यह लोगों के लिए एक निश्चित स्कोर पर गठबंधन करने के लिए आम है, इसलिए उस मामले में टाई को पहले सबमिट करने वाले द्वारा तोड़ दिया जाता है।
+-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ | pozscores | 0 | PRIMARY | 1 | id | A | 138296 | NULL | NULL | | BTREE | | | pozscores | 0 | game | 1 | game | A | NULL | NULL | NULL | YES | BTREE | | | pozscores | 0 | game | 2 | rank | A | NULL | NULL | NULL | YES | BTREE | | | pozscores | 1 | rank | 1 | rank | A | 138296 | NULL | NULL | YES | BTREE | | +-----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
जब एक उपयोगकर्ता अनुरोधों उच्च स्कोर, वे आम तौर पर: - "(समय MAX_TIME) स्कोर * 100000000 +"
+----------+---------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------+---------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | game | int(11) | YES | MUL | NULL | | | name | varchar(100) | YES | | NULL | | | playerId | varchar(50) | YES | | NULL | | | score | int(11) | YES | | NULL | | | time | datetime | YES | | NULL | | | rank | decimal(50,0) | YES | MUL | NULL | | +----------+---------------+------+-----+---------+----------------+
अनुक्रमित इस तरह दिखेगा इसलिए इस फ़ील्ड का मान लगभग के बराबर है "रैंक अवरोही सूची द्वारा क्रमबद्ध" में मनमाने ढंग से बिंदु से लगभग 75 उच्च स्कोर का अनुरोध करें। ये अनुरोध आम तौर पर "सभी समय" या पिछले 7 दिनों में स्कोर के लिए होते हैं।
एक सामान्य क्वेरी इस तरह दिखती है: "SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 0, 75;"
और 0.00 सेकंड में चलता है।
हालांकि, यदि आप "SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 10000, 75;"
सूची के अंत की ओर अनुरोध करते हैं और 0.06 सेकंड में चलता है।
"SELECT * FROM scoretable WHERE game=1 AND time>? ORDER BY rank DESC LIMIT 100000, 75;"
और 0.58 सेकेंड में चलता है।
ऐसा लगता है कि यह जल्द ही बहुत लंबा रास्ता शुरू कर देगा क्योंकि हर दिन कई हजार नए स्कोर जमा किए जाते हैं!
इसके अतिरिक्त, दो अन्य प्रकार के प्रश्न हैं, जो रैंक ऑर्डर सूची में आईडी द्वारा किसी विशेष प्लेयर को खोजने के लिए उपयोग किए जाते हैं। वे इस तरह दिखेगा:
"SELECT * FROM scoretable WHERE game=1 AND time>? AND playerId=? ORDER BY rank DESC LIMIT 1"
एक
"SELECT count(id) as count FROM scoretable WHERE game=1 AND time>? AND rank>[rank returned from above]"
मेरा प्रश्न द्वारा पीछा किया जाता: क्या यह एक विश्वसनीय प्रणाली बनाने के लिए किया जा सकता है? मैं बहुत जल्द लाखों की बढ़ती पंक्तियों की संख्या देख सकता हूं। मैं उम्मीद कर रहा था कि कुछ स्मार्ट इंडेक्स चुनने में मदद मिलेगी, लेकिन सुधार केवल मामूली रहा है।
अद्यतन:
mysql> explain SELECT * FROM scoretable WHERE game=1 AND time>0 ORDER BY rank DESC LIMIT 100000, 75; +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+ | 1 | SIMPLE | scoretable| range | game | game | 5 | NULL | 138478 | Using where | +----+-------------+-----------+-------+---------------+------+---------+------+--------+-------------+
समाधान मिला: यहाँ एक लाइन की व्याख्या है!
मैंने समस्या को हल किया है इस धागे से कुछ पॉइंटर्स को धन्यवाद। क्लस्टर्ड इंडेक्स करना बिल्कुल वही था जो मुझे चाहिए था, इसलिए मैंने टेबल को MySQL में MyoDB का उपयोग करने के लिए परिवर्तित किया, जो क्लस्टर इंडेक्स का समर्थन करता है। इसके बाद, मैंने आईडी फ़ील्ड को हटा दिया, और केवल प्राथमिक कुंजी को सेट किया (गेम एएससी, रैंक डीईएससी)। अब, सभी प्रश्न सुपर फास्ट चलाते हैं, इससे कोई फर्क नहीं पड़ता कि मैं किस ऑफसेट का उपयोग करता हूं। व्याख्या से पता चलता है कि कोई अतिरिक्त सॉर्टिंग नहीं की जा रही है, और ऐसा लगता है कि यह आसानी से सभी यातायात को संभालने में सक्षम है।
उपयोग मोंगो डीबी यह वेब पैमाने है। – anon
यह अजीब बात है कि टिप्पणियों को कम करना संभव नहीं है ("मोंगो डीबी का उपयोग करें। यह वेब स्केल है।") – zerkms
@ user509841: कुछ बताएं। – zerkms