2011-02-01 18 views
7

मेरे पास एक ऑनलाइन गेम के लिए एक सरल उच्च स्कोर सेवा है, और यह अपेक्षा से अधिक लोकप्रिय हो गया है। उच्च स्कोर एक 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 का उपयोग करने के लिए परिवर्तित किया, जो क्लस्टर इंडेक्स का समर्थन करता है। इसके बाद, मैंने आईडी फ़ील्ड को हटा दिया, और केवल प्राथमिक कुंजी को सेट किया (गेम एएससी, रैंक डीईएससी)। अब, सभी प्रश्न सुपर फास्ट चलाते हैं, इससे कोई फर्क नहीं पड़ता कि मैं किस ऑफसेट का उपयोग करता हूं। व्याख्या से पता चलता है कि कोई अतिरिक्त सॉर्टिंग नहीं की जा रही है, और ऐसा लगता है कि यह आसानी से सभी यातायात को संभालने में सक्षम है।

+3

उपयोग मोंगो डीबी यह वेब पैमाने है। – anon

+7

यह अजीब बात है कि टिप्पणियों को कम करना संभव नहीं है ("मोंगो डीबी का उपयोग करें। यह वेब स्केल है।") – zerkms

+1

@ user509841: कुछ बताएं। – zerkms

उत्तर

4

यह देखकर कि कोई लेकर्स नहीं है, मैं इसे एक शॉट दूंगा। मैं एक SQL सर्वर पृष्ठभूमि से हूँ, लेकिन एक ही विचार लागू होते हैं।

कुछ सामान्य टिप्पणियों:

  • आईडी स्तंभ काफी व्यर्थ है, और जब तक वहाँ अन्य तालिकाओं/प्रश्नों आप हमारे बारे में बता नहीं कर रहे हैं किसी भी सूचकांकों में भाग नहीं लेना चाहिए। वास्तव में, इसे आपकी अंतिम क्वेरी में भी होने की आवश्यकता नहीं है। आप COUNT (*) कर सकते हैं।
  • आपके क्लस्टर्ड इंडेक्स को आपके सबसे आम प्रश्नों को लक्षित करना चाहिए। इसलिए, खेल एएससी, समय डीईएससी, और रैंक डीईएससी पर एक क्लस्टर्ड इंडेक्स अच्छी तरह से काम करता है। समय के आधार पर छंटनी डीईएससी आमतौर पर इस तरह की ऐतिहासिक सारणी के लिए एक अच्छा विचार है जहां आप आमतौर पर सबसे हालिया चीजों में रुचि रखते हैं। आप दूसरे दिशा को क्रमबद्ध रैंक के साथ एक अलग इंडेक्स भी आज़मा सकते हैं, हालांकि मुझे यकीन नहीं है कि यह कितना लाभ होगा।
  • क्या आप वाकई SELECT * की आवश्यकता है? यदि आप कम कॉलम चुन सकते हैं, तो आप एक इंडेक्स बनाने में सक्षम हो सकते हैं जिसमें आपके चयन और कहां के लिए आवश्यक सभी कॉलम शामिल हैं।

1 मिलियन पंक्तियां वास्तव में इतना नहीं है। मैंने आपके जैसे टेबल को नमूना डेटा की 1,000,000 पंक्तियों के साथ बनाया है, और यहां तक ​​कि एक इंडेक्स (गेम एएससी, टाइम डीईएससी, और रैंक डीईएससी) के साथ भी, सभी प्रश्न 1 सेकंड से भी कम समय में चलते हैं।

(ही हिस्सा रहा playerId है के बारे में सुनिश्चित नहीं हूँ। प्रश्नों इतनी अच्छी तरह से है कि playerId आवश्यक हो नहीं लगता था प्रदर्शन किया। शायद आप अपने संकुल अनुक्रमणिका के अंत में जोड़ सकते हैं।)

+0

धन्यवाद! जैसा कि आप कहते हैं क्लस्टर इंडेक्स कैसे बनाऊंगा? –

+0

मैं इसे लेता हूं आपने इसे समझ लिया =) मुझे लगता है कि आपने अपना क्लस्टर इंडेक्स से बाहर समय और खिलाड़ी छोड़ा है। वे एक दिन उपयोगी होंगे, हालांकि अब जब मैं इसके बारे में सोचता हूं, आरोही समय करना बेहतर हो सकता है क्योंकि इंडेक्स के अंत में आवेषण होंगे। इसके बारे में पक्का भरोसा नहीं है। या आप सिर्फ मोंगो डीबी पर स्विच कर सकते हैं, क्योंकि यह वेब स्केल है =) – anon

संबंधित मुद्दे