2009-07-07 18 views
6

से बचने के लिए MySQL क्वेरी को अनुकूलित करें I MySQL का उपयोग करके मेरी साइट के लिए एक कस्टम फ़ोरम बनाया गया है। लिस्टिंग पृष्ठ अनिवार्य रूप से निम्न स्तंभों वाला एक तालिका है: विषय, अंतिम अपडेट, और # उत्तर"जहां का उपयोग करना; अस्थायी का उपयोग करना; फाइलों का उपयोग करना"

डीबी तालिका निम्न स्तंभ हैं:

id 
name 
body 
date 
topic_id 
email 

एक विषय "0" के topic_id है, और उत्तरों अपने माता पिता के विषय की topic_id है।

SELECT SQL_CALC_FOUND_ROWS 
    t.id, t.name, MAX(COALESCE(r.date, t.date)) AS date, COUNT(r.id) AS replies 
FROM 
    wp_pod_tbl_forum t 
LEFT OUTER JOIN 
    wp_pod_tbl_forum r ON (r.topic_id = t.id) 
WHERE 
    t.topic_id = 0 
GROUP BY 
    t.id 
ORDER BY 
    date DESC LIMIT 0,20; 

इस तालिका में लगभग 2,100 कुल आइटम हैं, और प्रश्न आमतौर पर 6 सेकंड तक लेते हैं। मैंने "topic_id" कॉलम में एक INDEX जोड़ा, लेकिन इससे ज्यादा मदद नहीं मिली। महत्वपूर्ण पुनर्गठन करने के लिए इस प्रश्न को तेज करने के कोई तरीके हैं?

संपादित करें: अभी तक काफी काम नहीं कर रहा है। मुझे ठीक से काम करने के लिए नीचे दिए गए उदाहरण नहीं मिल रहे हैं।

उत्तर

7
SELECT id, name, last_reply, replies 
FROM (
     SELECT topic_id, MAX(date) AS last_reply, COUNT(*) AS replies 
     FROM wp_pod_tbl_forum 
     GROUP BY 
       topic_id 
     ) r 
JOIN wp_pod_tbl_forum t 
ON  t.topic_id = 0 
     AND t.id = r.topic_id 
UNION ALL 
SELECT id, name, date, 0 
FROM wp_pod_tbl_forum t 
WHERE NOT EXISTS 
     (
     SELECT NULL 
     FROM wp_pod_tbl_forum r 
     WHERE r.topic_id = t.id 
     ) 
     AND t.topic_id = 0 
ORDER BY 
     date DESC 
LIMIT 0, 20 

तो अपनी मेज MyISAM या id एक PRIMARY KEY नहीं है, तो आप (topic_id, id) पर एक समग्र ondex बनाना होगा।

तो अपनी मेज InnoDB और id एक PRIMARY KEY है, बस (topic_id) पर एक सूचकांक करना होगा (id परोक्ष सूचकांक में जोड़ दिया जाएगा)।

अद्यतन

इस क्वेरी सबसे शायद और भी अधिक कुशल हो जाएगा, बशर्ते आप (topic_id, id) और (date, id) सूचक है:

    :

    प्रदर्शन जानकारी के लिए अपने ब्लॉग में यह लेख देखें

  • Selecting last forum posts

इस क्वेरी एक 100,000 पंक्तियों नमूना डेटा पर 30 ms में पूर्ण होती है:

SELECT id, name, last_reply, 
     (
     SELECT COUNT(*) 
     FROM wp_pod_tbl_forum fc 
     WHERE fc.topic_id = fl.topic_id 
     ) AS replies 
FROM (
     SELECT topic_id, date AS last_reply 
     FROM wp_pod_tbl_forum fo 
     WHERE id = (
       SELECT id 
       FROM wp_pod_tbl_forum fp 
       WHERE fp.topic_id = fo.topic_id 
       ORDER BY 
         fp.date DESC, fp.id DESC 
       LIMIT 1 
       ) 
       AND fo.topic_id <> 0 
     ORDER BY 
       fo.date DESC, fo.id DESC 
     LIMIT 20 
     ) fl 
JOIN wp_pod_tbl_forum ft 
ON  ft.id = fl.topic_id 
UNION ALL 
SELECT id, name, date, 0 
FROM wp_pod_tbl_forum t 
WHERE NOT EXISTS 
     (
     SELECT NULL 
     FROM wp_pod_tbl_forum r 
     WHERE r.topic_id = t.id 
     ) 
     AND t.topic_id = 0 
ORDER BY 
     last_reply DESC, id DESC 
LIMIT 20 

दोनों अनुक्रमित कुशल होने का इस प्रश्न के लिए आवश्यक हैं।

तो अपनी मेज InnoDBऔरid एक PRIMARY KEY है है, तो आप आईडी ऊपर indexes से मिटा सकते हैं।

+0

फ़ील्ड सूची में कॉलम 'डेट' संदिग्ध है ..? – Matt

+0

@ मैट: अद्यतन – Quassnoi

+0

@Quassnoi देखें - क्या आप समझा सकते हैं कि क्या हो रहा है? क्या "यूनियन ऑल" को "date_reply" को "date" के साथ बदल दिया गया है यदि विषय का कोई जवाब नहीं है? – Matt

1

आप इसे उप-सामानों (आंतरिक प्रश्नों के रूप में) में विभाजित करना चाहते हैं। मैं स्कीमा वास्तव में खेलने के लिए आवश्यकता होगी, लेकिन अगर आप

SELECT t.id, t.name, MAX(COALESCE(r.date, t.date)) AS date, COUNT(r.id) AS replies 
FROM (
    SELECT (id, name, date) 
    FROM wp_pod_tbl_forum 
    WHERE topic_id = 0 
) as t 
LEFT OUTER JOIN 
    wp_pod_tbl_forum r 
WHERE 
    r.topic_id = t.id 
GROUP BY 
    t.id 
ORDER BY 
    date DESC LIMIT 0,20; 

कि गति इसे एक छोटे से मदद मिल सकती है, तो यह और भी सर्वश्रेष्ठ उत्तर नहीं हो सकता है (त्रुटियां हो सकती हैं)।

ऐसा करने के कई तरीके हैं, लेकिन सबसे महत्वपूर्ण बात यह है कि एसक्यूएल ट्यूनिंग ऑपरेशन करने से पहले जितना संभव हो सके प्रत्येक सेट को कम करना है।

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