2012-10-23 4 views
8

यह "मेरे लिए अपना होमवर्क" जैसा लगता है, लेकिन मैं वास्तव में इस क्वेरी को कई पंक्तियों के साथ तालिका के खिलाफ जल्दी से चलाने की कोशिश कर रहा हूं। Here's a SQLFiddle जो स्कीमा दिखाता है (अधिक या कम)।सैकड़ों लाखों पंक्तियों के साथ तालिका के लिए क्वेरी अनुकूलित करें

मैंने इंडेक्स के साथ खेला है, जो कुछ आवश्यक कॉलम दिखाएगा, लेकिन इसमें बहुत सफलता नहीं मिली है। यहाँ create है:

CREATE TABLE `AuditEvent` (
    `auditEventId` bigint(20) NOT NULL AUTO_INCREMENT, 
    `eventTime` datetime NOT NULL, 
    `target1Id` int(11) DEFAULT NULL, 
    `target1Name` varchar(100) DEFAULT NULL, 
    `target2Id` int(11) DEFAULT NULL, 
    `target2Name` varchar(100) DEFAULT NULL, 
    `clientId` int(11) NOT NULL DEFAULT '1', 
    `type` int(11) not null, 
    PRIMARY KEY (`auditEventId`), 
    KEY `Transactions` (`clientId`,`eventTime`,`target1Id`,`type`), 
    KEY `TransactionsJoin` (`auditEventId`, `clientId`,`eventTime`,`target1Id`,`type`) 
) 

और (के एक संस्करण) select:

select ae.target1Id, ae.type, count(*) 
from AuditEvent ae 
where ae.clientId=4 
    and (ae.eventTime between '2011-09-01 03:00:00' and '2012-09-30 23:57:00') 
group by ae.target1Id, ae.type; 

मैं एक 'का उपयोग अस्थायी' और 'का उपयोग filesort' के साथ-साथ खत्म। मैंने count(*) को छोड़ने और select distinct का उपयोग करने की कोशिश की, जो 'फाइलों का उपयोग करना' का कारण नहीं बनता है। यदि काउंटर प्राप्त करने के लिए join पर कोई तरीका था तो यह शायद ठीक रहेगा।

मूल रूप से, ऑडिट रिकॉर्ड बनाए जाने पर लक्ष्य के लक्ष्य 1 नाम और लक्ष्य 2 नाम को ट्रैक करने के लिए निर्णय लिया गया था। मुझे उन नामों की भी आवश्यकता है (सबसे हाल ही में करेंगे)।

वर्तमान में क्वेरी (ऊपर, लापता लक्ष्य 1 नाम और लक्ष्य 2 नाम कॉलम के साथ) ~ 24 मिलियन रिकॉर्ड पर लगभग 5 सेकंड में चलती है। हमारा लक्ष्य सैकड़ों लाखों में है और हम चाहते हैं कि क्वेरी उन पंक्तियों के साथ प्रदर्शन जारी रखे (उम्मीद है कि इसे 1-2 मिनट से कम रखने की उम्मीद है, लेकिन हम इसे बेहतर बनाना चाहते हैं), लेकिन मेरा डर एक बार है हमने उस बड़ी मात्रा में डेटा को मारा जो यह नहीं करेगा (अतिरिक्त पंक्तियों को अनुकरण करने के लिए काम चल रहा है)।

मुझे अतिरिक्त फ़ील्ड प्राप्त करने की सर्वोत्तम रणनीति के बारे में निश्चित नहीं है। यदि मैं कॉलम सीधे select में जोड़ता हूं तो मैं क्वेरी पर 'अनुक्रमणिका का उपयोग' खो देता हूं। मैंने टेबल पर join की कोशिश की, जो 'इंडेक्स का उपयोग' रखता है लेकिन लगभग 20 सेकंड लेता है।

मैंने ईवेंटटाइम कॉलम को डेटाटाइम की बजाय int में बदलने का प्रयास किया लेकिन यह इंडेक्स उपयोग या समय को प्रभावित नहीं करता था।

+0

तुम क्या अपने वर्तमान क्वेरी समय है और क्या तहत समझते हैं:

यदि आप सवाल (जो आप काफी तेजी से विचार करें) आपकी क्वेरी के लिए उन दो क्षेत्रों को जोड़ने का तरीका है, तो बस निम्न प्रयास करें बस है "जल्दी जल्दी"? – feeela

+0

क्षमा करें, उन विवरणों को जोड़ा गया –

+0

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

उत्तर

3

आप शायद समझ में के रूप में, समस्या यहाँ सीमा हालत ae.eventTime between '2011-09-01 03:00:00' and '2012-09-30 23:57:00' जो है (जैसा कि हमेशा होता है) Transactions सूचकांक के कुशल उपयोग (कि सूचकांक वास्तव में clientId समीकरण और सीमा हालत के पहले भाग और के लिए ही इस्तेमाल किया जाता है टूट जाता है ग्रुपिंग के लिए इंडेक्स का उपयोग नहीं किया जाता है)।

अक्सर, समाधान (आपके मामले में, एक period स्तंभ, अवधियों में समूह eventTime लागू करने और एक period IN (1,2,3,4,5) साथ BETWEEN खंड की जगह) एक समानता चेक के साथ सीमा हालत को बदलने के लिए है। लेकिन यह आपकी मेज के लिए एक ओवरहेड बन सकता है।

एक अन्य समाधान है कि आप कोशिश कर सकते हैं एक और सूचकांक (शायद Transactions की जगह अगर यह अब और नहीं किया जाता है) को जोड़ने के लिए है: (clientId, target1Id, type, eventTime), और निम्न क्वेरी का उपयोग:

SELECT 
    ae.target1Id, 
    ae.type, 
    COUNT(
    NULLIF(ae.eventTime BETWEEN '2011-09-01 03:00:00' 
          AND '2012-09-30 23:57:00', 0) 
) as cnt, 
FROM AuditEvent ae 
WHERE ae.clientId=4 
GROUP BY ae.target1Id, ae.type; 

इस तरह, आप होगा एक) चाल: अंत करने के लिए सीमा हालत, ख), ग) सूचकांक क्वेरी के लिए सूचकांक कवर (कि क्वेरी डिस्क आईओ आपरेशन की जरूरत नहीं है)

UPD1 है समूह के लिए सूचकांक के उपयोग की अनुमति मुझे खेद है, yesteday मैंने आपकी पोस्ट को ध्यान से नहीं पढ़ा और ध्यान नहीं दिया कि आपकी समस्या target1Name और target2Name पुनर्प्राप्त करना है। सबसे पहले, मुझे यकीन नहीं है कि आप Using index के अर्थ को सही ढंग से समझते हैं। Using index की अनुपस्थिति का मतलब यह नहीं है कि क्वेरी के लिए कोई अनुक्रमणिका का उपयोग नहीं किया जाता है, Using index का अर्थ है कि इंडेक्स में एक सबक्वायरी निष्पादित करने के लिए पर्याप्त डेटा होता है (जो इंडेक्स कवर होता है)। चूंकि target1Name और target2Name किसी भी इंडेक्स में शामिल नहीं हैं, तो उन्हें प्राप्त करने वाली उपक्खी में Using index नहीं है।

SELECT a1.target1Id, a1.type, cnt, target1Name, target2Name 
FROM (
    select ae.target1Id, ae.type, count(*) as cnt, MAX(auditEventId) as max_id 
    from AuditEvent ae 
    where ae.clientId=4 
     and (ae.eventTime between '2011-09-01 03:00:00' and '2012-09-30 23:57:00') 
    group by ae.target1Id, ae.type) as a1 
JOIN AuditEvent a2 ON a1.max_id = a2.auditEventId 
; 
+0

दोनों वास्तव में वैध उत्तर हैं; मैं क्वेरी के प्रदर्शन को बढ़ाने/इसे बनाने के विभिन्न तरीकों पर सलाह प्राप्त करने के लिए देख रहा था, और इसके अलावा मैं गैर अनुक्रमित कॉलम को पुनर्प्राप्त करने का सबसे अच्छा तरीका आश्चर्यचकित था। आपके दोनों सुझावों ने मेरे द्वारा किए गए प्रश्नों की तुलना में प्रदर्शन में सुधार किया है! –

+0

@nickSpacek, ठीक है, मुझे खुशी है कि यह मदद मिली =) – newtover

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