2009-08-18 16 views
6

को गति देने का कोई भी तरीका मेरे पास 2 टेबल हैं। 1 संगीत है और 2 सुनोट्रैक है। सुनोट्रैक प्रत्येक गीत के अद्वितीय नाटकों को ट्रैक करता है। मैं महीने के लोकप्रिय गाने के परिणाम प्राप्त करने की कोशिश कर रहा हूं। मुझे अपने परिणाम मिल रहे हैं लेकिन वे बहुत अधिक समय ले रहे हैं। नीचे अपनी तालिका और क्वेरीMySQL धीमे होने पर धीमा।

430,000 पंक्तियों

CREATE TABLE `listentrack` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `sessionId` varchar(50) NOT NULL, 
    `url` varchar(50) NOT NULL, 
    `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `ip` varchar(150) NOT NULL, 
    `user_id` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM AUTO_INCREMENT=731306 DEFAULT CHARSET=utf8 

12500 पंक्तियों

CREATE TABLE `music` (
    `music_id` int(11) NOT NULL AUTO_INCREMENT, 
    `user_id` int(11) NOT NULL, 
    `title` varchar(50) DEFAULT NULL, 
    `artist` varchar(50) DEFAULT NULL, 
    `description` varchar(255) DEFAULT NULL, 
    `genre` int(4) DEFAULT NULL, 
    `file` varchar(255) NOT NULL, 
    `url` varchar(50) NOT NULL, 
    `allow_download` int(2) NOT NULL DEFAULT '1', 
    `plays` bigint(20) NOT NULL, 
    `downloads` bigint(20) NOT NULL, 
    `faved` bigint(20) NOT NULL, 
    `dateadded` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`music_id`) 
) ENGINE=MyISAM AUTO_INCREMENT=15146 DEFAULT CHARSET=utf8 


SELECT COUNT(listenTrack.url) AS total, listenTrack.url 
FROM listenTrack 
LEFT JOIN music ON music.url = listenTrack.url 
WHERE DATEDIFF(DATE(date_created),'2009-08-15') = 0 
GROUP BY listenTrack.url 
ORDER BY total DESC 
LIMIT 0,10 

इस क्वेरी बहुत जटिल नहीं है और पंक्तियों बहुत बड़ी नहीं कर रहे हैं, मुझे नहीं लगता है।

क्या इसे गति देने का कोई तरीका है? या आप एक बेहतर समाधान का सुझाव दे सकते हैं? यह हर महीने की भिखारी पर एक क्रॉन नौकरी होने जा रहा है, लेकिन मैं दिन के परिणामों के साथ भी करना चाहूंगा।

ओह btw मैं इस स्थानीय रूप से चला रहा हूँ, 4 मिनट चलाने के लिए, लेकिन prod पर ले जाता है लगभग 45 सेकेंड

उत्तर

10

मैं एक एसक्यूएल सर्वर लड़का के अधिक एम लेकिन इन अवधारणाओं को लागू करना चाहिए।

मैं अनुक्रमित जोड़ेंगे:,

  1. ListenTrack पर यूआरएल के साथ एक सूचकांक जोड़ सकते हैं और date_created
  2. संगीत पर, यूआरएल के साथ एक सूचकांक जोड़ने

इन अनुक्रमित क्वेरी गति चाहिए बहुत ऊपर (मैं मूल रूप से तालिका के नाम मिश्रित था - नवीनतम संपादन में तय)।

+0

मेरा मानना ​​है कि इंडेक्स तालिका के नाम फ़्लिप किए गए हैं। मैं पहली बार ऐसा करने के लिए उलझ गया और पोस्ट करने से पहले इसे पकड़ा। – TheJacobTaylor

+0

TheJacobTaylor सही था, मेरे पास टेबल नाम पीछे थे। मैंने इसे ठीक कर दिया है। –

+0

मेरे पास सवाल है, हम दोनों ने उन्हें पीछे क्यों लाया? मैंने फिर से पोस्ट को देखा, लेकिन मैंने ट्रिगर को नहीं देखा जो मैंने गलत किया। – TheJacobTaylor

4

एक सूचकांक में शामिल होने के साथ में मदद मिलेगी बनाने का प्रयास करें:

CREATE INDEX idx_url ON music (url); 
5

अधिकांश भाग के लिए आपको जॉइन में उपयोग किए जाने वाले किसी भी कॉलम को भी इंडेक्स करना चाहिए। आपके मामले में, आपको listentrack.url और music.url

@jeff s - एक अनुक्रमणिका music.date_created मदद नहीं करेगा क्योंकि आप पहले किसी फ़ंक्शन के माध्यम से इसे चला रहे हैं, इसलिए MySQL उस कॉलम पर किसी इंडेक्स का उपयोग नहीं कर सकता है। अक्सर, आप एक प्रश्न के पुनर्लेखन कर सकते हैं ताकि अनुक्रमित संदर्भित स्तंभ स्थिर प्रयोग किया जाता है की तरह है:

date_created >= '2009-08-15' and date_created < '2009-08-15' 

यह रिकॉर्ड 2009-08-15 से हैं को फ़िल्टर करें और किसी भी अनुक्रमित की अनुमति देगा

DATEDIFF(DATE(date_created),'2009-08-15') = 0 

हो जाता है उम्मीदवार होने के लिए उस कॉलम पर। ध्यान दें कि MySQL उस अनुक्रमणिका का उपयोग नहीं कर सकता है, यह अन्य कारकों पर निर्भर करता है।

आपका सबसे अच्छा शर्त music.url

इन 2 अनुक्रमित पर listentrack(url, date_created) और फिर एक और सूचकांक पर एक दोहरी सूचकांक बनाने के लिए इस विशेष क्वेरी को कवर किया जाएगा है।

ध्यान दें कि यदि आप इस क्वेरी पर EXPLAIN चलाते हैं तो आपको अभी भी using filesort प्राप्त होगा क्योंकि इसे ऑर्डर द्वारा ऑर्डर करने के लिए डिस्क पर एक अस्थायी तालिका में रिकॉर्ड लिखना होगा।

सामान्य रूप से आपको यह प्रश्न प्राप्त करने के लिए EXPLAIN के तहत अपनी क्वेरी हमेशा चलनी चाहिए कि MySQL क्वेरी निष्पादित कैसे करेगा और फिर वहां से जाएं।

http://dev.mysql.com/doc/refman/5.0/en/using-explain.html

+0

क्रूर समय। :) उत्कृष्ट जवाब। सेकंड से मुझे मारो। – TheJacobTaylor

+0

धन्यवाद बहुत बहुत उपयोगी लगता है। मैं आपके लिंक का पालन करूंगा और पढ़ूंगा और अपना उदाहरण – kayem

3

मुझे लगता है कि मैं पहले स्पष्ट याद किया हो सकता है: EXPLAIN दस्तावेज़ देखें। आप संगीत तालिका में क्यों शामिल हो रहे हैं? आप उस तालिका में डेटा का उपयोग नहीं कर रहे हैं और आप बाएं शामिल कर रहे हैं, जिसकी आवश्यकता नहीं है, है ना? मुझे लगता है कि यह तालिका क्वेरी में है, यह बहुत धीमी हो जाएगी और कोई मूल्य नहीं जोड़ पाएगी। जब तक यूआरएल समावेशन की आवश्यकता न हो, तब तक संगीत के सभी संदर्भ लें, इस मामले में आपको एक मेल खाने के बिना एक पंक्ति शामिल न करने के लिए मजबूर करने के लिए सही शामिल होना चाहिए।


अन्य नए इंडेक्स जोड़ देंगे, जैसा कि दूसरों का उल्लेख है। विशेष रूप से मैं जोड़ता हूं: संगीत यूआरएल listentrack date_created, url

इससे आपके टन में शामिल होने में सुधार होगा।

फिर मैं क्वेरी को देखता हूं, आप सिस्टम की प्रत्येक पंक्ति पर काम करने के लिए सिस्टम को मजबूर कर रहे हैं। तिथि प्रतिबंध को एक सीमा के रूप में दोबारा बेहतर करना बेहतर होगा।

मेरे सिर के ऊपर से वाक्य रचना के बारे में सुनिश्चित नहीं: जहां '2009-08-15 00:00:00' < = date_created < 2009-08-16 00:00:00

यही चाहिए उपयुक्त रिकॉर्ड का पता लगाने के लिए इसे तेजी से सूचकांक का उपयोग करने की अनुमति दें। संगीत पर संयुक्त दो प्रमुख इंडेक्स को तारीख और यूआरएल के आधार पर रिकॉर्ड ढूंढने की अनुमति देनी चाहिए। आपको प्रयोग करना चाहिए, वे इंडेक्स पर डेट_क्रेटेड, दूसरी दिशा यूआरएल में जाने से बेहतर हो सकते हैं।

इस क्वेरी के लिए समझाया गया योजना दोनों के लिए दाएं हाथ कॉलम पर "अनुक्रमणिका का उपयोग करके" कहनी चाहिए। इसका मतलब है कि आपको अपनी रकम की गणना करने के लिए तालिका में डेटा को हिट नहीं करना पड़ेगा।

मैं उन स्मृति सेटिंग्स को भी जांचूंगा जिन्हें आपने MySQL के लिए कॉन्फ़िगर किया है। ऐसा लगता है कि आपके पास पर्याप्त स्मृति आवंटित नहीं है। सर्वर आधारित सेटिंग्स और थ्रेड आधारित सेटिंग्स के बीच मतभेदों पर बहुत सावधान रहें। 10 एमबी कैश वाला सर्वर बहुत छोटा है, 10 एमबी कैश वाला थ्रेड बहुत मेमोरी का उपयोग कर सकता है।

याकूब

+0

मैं उस तालिका में डेटा का उपयोग कर रहा हूं लेकिन मैं डीबगजिन था जहां धीमापन आया था। कोई 1 सेकंड क्वेरी में शामिल नहीं है। Music.url पर idx अनुक्रमणिका जोड़ने के बाद जुड़ें 7 सेकेंड पर दौड़ें और संगीत जोड़ना। इसे 10 – kayem

+0

तक धक्का दिया गया है क्या आप "असली" क्वेरी या इंडेक्स के साथ समझाया गया योजना पोस्ट कर सकते हैं? हम एक दिन (परिमाण के क्रम) के बारे में कितने रिकॉर्ड बात कर रहे हैं? आप बॉक्स पर कितनी मेमोरी का उपयोग कर रहे हैं? इंडेक्स और डेटा कैश, या इनो डीबी पर सिर्फ कैश, महत्वपूर्ण और ठीक करने में आसान हैं। – TheJacobTaylor

0

आप अनुक्रमित जोड़ने के बाद तो आप date_created के लिए एक नया स्तंभ जोड़ने एक unix_timestamp, जो गणित आपरेशन तेज कर देगा होने के लिए पता लगाने के लिए कर सकते हैं।

मुझे यकीन नहीं है कि आपके पास diff फ़ंक्शन क्यों है, जैसा कि ऐसा लगता है कि आप किसी विशेष तारीख पर अपडेट की गई सभी पंक्तियों की तलाश में हैं।

आप अपनी क्वेरी को देखना चाहते हैं क्योंकि ऐसा लगता है कि एक त्रुटि है।

यदि आप यूनिट परीक्षण का उपयोग करते हैं तो आप अपनी क्वेरी के परिणामों और इसके बजाय यूनिक्स टाइमस्टैम्प का उपयोग करके एक क्वेरी की तुलना कर सकते हैं।

1

आप दोनों टेबलों में यूआरएल क्यों दोहरा रहे हैं?

सूची के बजाय एक music_id पकड़ें, और उस पर शामिल हों। पाठ खोज के साथ-साथ अतिरिक्त अनुक्रमणिका से छुटकारा पाता है।

इसके अलावा, यह तर्कसंगत रूप से अधिक सही है। आप उस समय को ट्रैक कर रहे हैं कि एक विशेष ट्रैक यूआरएल नहीं सुना गया था। अगर यूआरएल बदलता है तो क्या होगा?

0

आप दोनों टेबलों के यूआरएल फ़ील्ड में एक इंडेक्स जोड़ना चाहते हैं।

ने कहा है कि, जब मैं mysql से SQL Server 2008 में परिवर्तित करता हूं, वही प्रश्न और समान डेटाबेस संरचनाओं के साथ, क्वेरी तीव्रता के 1-3 ऑर्डर तेजी से चलती हैं।

मुझे लगता है कि इसमें से कुछ को rdbms (mysql अनुकूलक इतने अच्छे नहीं हैं ...) के साथ करना था और उनमें से कुछ को rdbms रिजर्व सिस्टम संसाधनों के साथ क्या करना पड़ सकता था। हालांकि, तुलना उत्पादन प्रणालियों पर की गई थी जहां केवल डीबी चलती थी।

2

प्री-ग्रुपिंग और फिर शामिल होने से चीजें MySQL/MyISAM के साथ बहुत तेज हो जाती हैं।

SELECT 
    total, a.url, title 
FROM 
(
    SELECT COUNT(*) as total, url 
    from listenTrack 
    WHERE DATEDIFF(DATE(date_created),'2009-08-15') = 0 
    GROUP BY url 
    ORDER BY total DESC 
    LIMIT 0,10 
) as a 
LEFT JOIN music ON music.url = a.url 
; 

पी.एस.:

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

+0

पूरी तरह से सहमत हैं –

0

यह नीचे शायद क्वेरी को तेज़ करने के लिए काम करेगा।

INDEX music_url_index पर संगीत (यूआरएल) बीटीआरई का उपयोग करें; INDEX LearnTrack_url_index CRETTrack (url) पर BTREE का उपयोग करें;

आपको वास्तव में तुलना की जा रही तुलना और पंक्ति स्कैन की कुल संख्या जानने की आवश्यकता है। उस उत्तर को प्राप्त करने के लिए यहां कोड को देखें, http://www.siteconsortium.com/h/p1.php?id=mysql002 को समझाने के तरीके को कैसे करें।

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