2011-11-29 20 views
7

मैं MySQL के लिए बहुत नया हूं और यहां से अधिक अनुभवी लोगों के महान समर्थन के लिए धन्यवाद, मैं प्रक्रिया में बहुत कुछ सीखते समय संघर्ष करने के लिए प्रबंधन कर रहा हूं।मैं इस MySQL क्वेरी के प्रदर्शन को सरल/सुधार कैसे कर सकता हूं?

मेरे पास एक प्रश्न है जो मैं चाहता हूं कि वास्तव में करता है। हालांकि, यह मेरे लिए बेहद गन्दा दिखता है और मुझे यकीन है कि इसे सरल बनाने का एक तरीका होना चाहिए।

प्रदर्शन के लिए यह प्रश्न कैसे बेहतर और अनुकूलित किया जा सकता है?

बहुत धन्यवाद

  $sQuery = " 
     SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))." 

    FROM $sTable b 
    LEFT JOIN (
    SELECT COUNT(*) AS projects_count, a.songs_id 

    FROM $sTable2 a 
    GROUP BY a.songs_id 
) bb ON bb.songs_id = b.songsID 

LEFT JOIN (
    SELECT AVG(rating) AS rating, COUNT(rating) AS ratings_count, c.songid 

FROM $sTable3 c 

    GROUP BY c.songid 
) bbb ON bbb.songid = b.songsID 

LEFT JOIN (
    SELECT c.songid, c.userid, 

    CASE WHEN EXISTS 
    ( 
     SELECT songid 
     FROM $sTable3 
     WHERE songid = c.songid 
    ) Then 'User Voted' 
    else 
    (
     'Not Voted' 
    ) 
    end 
    AS voted 
FROM $sTable3 c 
WHERE c.userid = $userid 


    GROUP BY c.songid 
) bbbb ON bbbb.songid = b.songsID 

संपादित करें: यहाँ क्या क्वेरी कर रही है का वर्णन है: -

मैं तीन टेबल है:

  • $ स्थिर = गाने की एक तालिका (गीतकार, mp3link, artwork, useruploadid आदि)

  • $ sTable2 (projectid, songid, प्रोजेक्ट नाम आदि) उन्हें से जुड़ा हुआ गीतों के साथ परियोजनाओं की एक तालिका

  • $ sTable3 गीत रेटिंग (songid, उपयोगकर्ता आईडी, रेटिंग)

की एक तालिका = =

यह सभी डेटा एक JSON सरणी के लिए आउटपुट है और मेरे एप्लिकेशन में एक तालिका में प्रदर्शित किया गया है ताकि गाने की रेटिंग प्रदान की जा सके, परियोजनाओं और रेटिंग डेटा के साथ मिलकर।

  1. $ से सभी पंक्तियों को स्थिर
  2. songsID पर $ sTable2 को शामिल एकत्र और इस तालिका है जिसमें पंक्तियों (परियोजनाओं) की संख्या की गणना -:

    क्वेरी ही इस क्रम में निम्नलिखित करता है वही गीत आईडी

  3. गानों आईडी पर $ स्थिर 3 में शामिल हो जाता है और इस तालिका में कॉलम 'रेटिंग' का औसत काम करता है जिसमें एक ही गाने आईडी
  4. इस बिंदु पर यह $ sTable3 में पंक्तियों की कुल संख्या की भी गणना करता है वोटों की कुल संख्या प्रदान करने के लिए एक ही गीत आईडी ।
  5. अंततः यह इन सभी पंक्तियों पर एक चेक करता है यह देखने के लिए कि $ userid (जो लॉग इन उपयोगकर्ता की आईडी वाला एक चर है) यह जांचने के लिए कि प्रत्येक उपयोगकर्ता के लिए $ sTable3 में 'userid' स्टोर से मेल खाता है या नहीं उपयोगकर्ता पहले से ही दिए गए गीत आईडी पर मतदान कर चुका है या नहीं। यदि यह मेल खाता है तो यह "उपयोगकर्ता वोट" देता है अगर यह "वोट नहीं दिया गया" लौटाता है। यह इसे मेरे जेएसओएन सरणी में एक अलग कॉलम के रूप में आउटपुट करता है जिसे मैं अपने ऐप में क्लाइंटसाइड के खिलाफ जांचता हूं और कक्षा में जोड़ता हूं।

यदि कोई और विवरण है तो किसी को भी जरूरत है, कृपया मुझे बताएं। सबको शुक्रीया।

संपादित करें:

Aurimis 'उत्कृष्ट पहला प्रयास मैं एक और अधिक सरल समाधान पर में बंद कर रहा हूँ करने के लिए धन्यवाद।

यह वह कोड है जिसे मैंने उस सुझाव के आधार पर आजमाया है।

SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ", implode(", ", $aColumns))." 

    FROM 
     (SELECT 
     $sTable.songsID, COUNT(rating) AS ratings_count, 
     AVG(rating) AS ratings 
     FROM $sTable 
     LEFT JOIN $sTable2 ON $sTable.songsID = $sTable2.songs_id 
     LEFT JOIN $sTable3 ON $sTable.songsID = $sTable3.songid 
     GROUP BY $sTable.songsID) AS A 
    LEFT JOIN $sTable3 AS B ON A.songsID = B.songid AND B.userid = $userid 

हालांकि कई समस्याएं हैं। मैं अपने जवाब की पहली पंक्ति को दूर करने के लिए किया था के रूप में यह एक 500 आंतरिक सर्वर त्रुटि के कारण होता है:

IF(B.userid = NULL, "Not voted", "User Voted") AS voted 

जाहिर है अब 'मतदान की जांच' कार्यक्षमता खो दिया है।

इसके अलावा और अधिक महत्वपूर्ण बात यह है कि यह मेरी सरणी में परिभाषित सभी कॉलम वापस नहीं कर रहा है, केवल गीत आईडी। मेरा JSON 'फील्ड सूची' में अज्ञात कॉलम 'song_name' देता है - अगर मैं इसे अपने $ aColumns सरणी से हटा देता हूं तो यह निश्चित रूप से अगले पर जाएगा।

मैं अपनी स्क्रिप्ट की शुरुआत में अपने कॉलम को परिभाषित कर रहा हूं क्योंकि इस सरणी का उपयोग फ़िल्टरिंग और JSON एन्कोड के आउटपुट को एक साथ रखने के लिए किया जाता है। यह $ aColumns की परिभाषा है: -।

$aColumns = array('songsID', 'song_name', 'artist_band_name', 'author', 'song_artwork', 'song_file', 'genre', 'song_description', 'uploaded_time', 'emotion', 'tempo', 'user', 'happiness', 'instruments', 'similar_artists', 'play_count', 'projects_count', 'rating', 'ratings_count', 'voted'); 

आदेश जल्दी से $ स्थिर चयन करने के लिए क्वेरी मैं सबक्वेरी के भीतर पहली पंक्ति संशोधित के बाकी का परीक्षण करने में * बजाय $ sTable.songsID ($ स्थिर याद गीत तालिका है)

फिर ... क्वेरी स्पष्ट रूप से काम करती है, लेकिन पाठ्यक्रम के भयानक प्रदर्शन के साथ। लेकिन केवल 5000 गीत परीक्षण डेटासेट में से 24 गाने लौटे। इसलिए मैंने आपकी पहली 'जॉइन' को 'बाएं जॉइन' में बदल दिया ताकि सभी 5000 गाने वापस लौटे। क्वेरी को स्पष्ट करने के लिए गानों की तालिका में सभी पंक्तियों को वापस करने की आवश्यकता है, लेकिन प्रत्येक गीत के लिए परियोजनाओं और रेटिंग तालिकाओं से डेटा के विभिन्न अतिरिक्त बिट्स के साथ।

तो ... हम वहां जा रहे हैं और मुझे यकीन है कि यह एक बेहतर तरीका है कि इसे कुछ संशोधन की आवश्यकता है। अब तक आपकी सहायता के लिए धन्यवाद ऑरिमिस।

+0

ऐसा लगता है कि जो व्यक्ति क्वेरी लिखा MySQL – newtover

+0

लिए नया नहीं था मैं इसे अपने आप 'googling', यहाँ विभिन्न सवाल पूछ, और पढ़कर लिखा था बहुत। हालांकि, मैंने संक्षेप में जो कुछ भी हासिल करना है, उसे प्राप्त करने के लिए एक 'काम करने' क्वेरी में कई टुकड़ों को एक साथ रखा है। हालांकि मैं समझता हूं कि क्वेरी का प्रत्येक भाग क्या करता है और यह क्यों काम करता है, मुझे यह जानने का अनुभव नहीं है कि मैं इसे एक प्रभावशाली तरीके से कर रहा हूं या नहीं। अन्य भाषाओं के साथ मेरे अनुभव से मेरा अनुमान मुझे बताता है कि मैं नहीं हूं। इसलिए मैं अधिक अनुभवी MySQL डेवलपर्स की सलाह का स्वागत करता हूं। :) – gordyr

+0

क्या आप बता सकते हैं कि अपेक्षित परिणाम क्या होना चाहिए? – Peter

उत्तर

3
SELECT SQL_CALC_FOUND_ROWS 
    songsID, song_name, artist_band_name, author, song_artwork, song_file, 
    genre, song_description, uploaded_time, emotion, tempo, 
    `user`, happiness, instruments, similar_artists, play_count, 
    projects_count, 
    rating, ratings_count, 
    IF(user_ratings_count, 'User Voted', 'Not Voted') as voted 
FROM (
    SELECT 
     sp.songsID, projects_count, 
     AVG(rating) as rating, 
     COUNT(rating) AS ratings_count, 
     COUNT(IF(userid=$userid, 1, NULL)) as user_ratings_count 
    FROM (
     SELECT songsID, COUNT(*) as projects_count 
     FROM $sTable s 
     LEFT JOIN $sTable2 p ON s.songsID = p.songs_id 
     GROUP BY songsID) as sp 
    LEFT JOIN $sTable3 r ON sp.songsID = r.songid 
    GROUP BY sp.songsID) as spr 
JOIN $sTable s USING (songsID); 

आप निम्न अनुक्रमित की आवश्यकता होगी:

  • (songs_id) $ पर sTable2
  • समग्र (songid, रेटिंग, उपयोगकर्ता आईडी) $ sTable3

क्वेरी के पीछे एक विचार पर:

  • सबक्वेरी INTs के साथ काम इतना है कि सबक्वेरी का परिणाम आसानी से स्मृति
  • बाईं मिलती अलग से वर्गीकृत किया है कार्तीय उत्पाद
  • उपयोगकर्ता वोट ही सबक्वेरी में गिने जाते हैं को कम करने के रूप में अन्य रेटिंग्स महंगा से बचने के लिए सहसंबद्ध में फिट सबक्वेरी
  • सभी othe जानकारी में शामिल होने के अंतिम आईबी लिया गया है
+0

सुझाव newtover के लिए धन्यवाद। सप्ताहांत के बाद तक मैं आपके समाधान की जांच करने की स्थिति में नहीं रहूंगा। एक त्वरित रूप से देखने से मुझे सब अच्छा लगता है, मैं आपको सोमवार को बता दूंगा। :-) – gordyr

+0

शानदार ... यह पूरी तरह से काम करता है। इसे निष्पादन के संदर्भ में समझना और असीम रूप से अधिक सुरुचिपूर्ण है। मैंने अभी तक कोई प्रदर्शन परीक्षण नहीं किया है, लेकिन शुरुआती छाप से यह निश्चित रूप से कोई बुरा नहीं है और आपकी क्वेरी का उपयोग करने से भविष्य में समायोज्य को कहीं भी आसान बनाना होगा क्योंकि यह संरचनात्मक रूप से कहीं बेहतर है। विशाल धन्यवाद newtover, वास्तव में महान जवाब! – gordyr

+0

@gordyr, आपका स्वागत है =) – newtover

1

मुझे अपने विवरण के आधार पर प्रयास करने दें, क्वेरी नहीं। स्पष्टता के लिए Table3 इंगित करने के लिए Table2 और Ratings इंगित करने के लिए , Projects इंगित करने के लिए मैं Songs का उपयोग करूंगा।

SELECT 
    /* [column list again] */, 
    IF(B.userid = NULL, "Not voted", "Voted") as voted 
FROM 
    (SELECT 
    Songs.SongID, count(rating) as total_votes, 
    avg(rating) as average_rating /*[,.. other columns as you need them] */ 
    FROM Songs 
    JOIN Projects ON Songs.SongID = Projects.SongID 
    LEFT JOIN Ratings ON Songs.SongID = Ratings.SongID 
    GROUP BY Songs.SongID) as A 
LEFT JOIN Ratings as B ON A.SongID = B.SongID AND B.userid = ? /* your user id */ 

जैसा कि आप देख, आप एक में गीत पर सभी जानकारी प्राप्त कर सकते हैं, अपेक्षाकृत सरल क्वेरी (बस से समूह का उपयोग कर और()/औसत() फ़ंक्शन गिनती)। जानकारी प्राप्त करने के लिए कि किसी विशेष उपयोगकर्ता द्वारा किसी गीत को रेट किया गया था, एक सबक्वायरी की आवश्यकता होती है - जहां आप बाएं जॉइन कर सकते हैं, और यदि उपयोगकर्ता आईडी खाली है - तो आप जानते हैं कि उसने मतदान नहीं किया है।

अब, मैं आपकी क्वेरी को गहराई से नहीं देखता, क्योंकि यह वास्तव में जटिल दिखता है।हो सकता है कि मैं कुछ छूट गया हो - यदि ऐसा है, विवरण अपडेट कर लें और मैं फिर से कोशिश कर सकते हैं :)

+0

यह महान ऑरिमा दिखता है, सुझाव के लिए बहुत धन्यवाद। मैं इसे एक और घंटे के लिए परीक्षण करने की स्थिति में नहीं रहूंगा। इसकी प्रगति के बारे में मेरे द्वारा आपको बताया जाएगा। – gordyr

+0

धन्यवाद औरइमास ... मैंने आपके सुझावों का प्रयास करने के बाद से अपने निष्कर्षों के साथ अपना प्रश्न अपडेट कर लिया है। खुश होती है। :) – gordyr

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