2009-12-23 12 views
6

मेरे पास एक सारणी है जिसमें एक टेबल के लिए एक विदेशी कुंजी है जो कुछ ब्लॉब डेटा स्टोर करती है। जब मैं मुख्य तालिका पर किसी शर्त के साथ टेबल पर एक आंतरिक जुड़ता हूं तो जॉइन प्रकार 'इंडेक्स' से 'ऑल' तक जाता है। मैं इसे टालना चाहूंगा क्योंकि मेरी ब्लॉब टेबल गीगाबाइट के दसियों के क्रम में है। मैं इससे कैसे बच सकता हूं?मैं इस मूल आंतरिक शामिल होने के साथ पूर्ण तालिका स्कैन से कैसे बचूं?

यहाँ बुनियादी भीतरी में शामिल होने है:

EXPLAIN SELECT m.id, b.id, b.data 
     FROM metadata m, blobstore b 
     WHERE m.fkBlob = b.id; 

1, 'SIMPLE', 'm', 'index', 'fk_blob', 'fk_blob', '4', '', 1, 'Using index' 
1, 'SIMPLE', 'b', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'blob_index.m.fkBlob', 1, '' 

यहाँ मैं मुख्य मेज पर एक शर्त जोड़:

EXPLAIN SELECT m.id, b.id, b.data 
     FROM metadata m, blobstore b 
     WHERE m.fkBlob = b.id AND m.start < '2009-01-01'; 
1, 'SIMPLE', 'b', 'ALL', 'PRIMARY', '', '', '', 1, '' 
1, 'SIMPLE', 'm', 'ref', 'fk_blob,index_start', 'fk_blob', '4', 'blob_index.b.id', 1, 'Using where' 

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

DROP TABLE IF EXISTS `blob_index`.`metadata`; 
    CREATE TABLE `blob_index`.`metadata` (
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
     `fkBlob` int(10) unsigned NOT NULL, 
     `start` datetime NOT NULL, 
     PRIMARY KEY (`id`), 
     KEY `fk_blob` (`fkBlob`), 
     KEY `index_start` (`start`), 
     CONSTRAINT `fk_blob` FOREIGN KEY (`fkBlob`) REFERENCES `blobstore` (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 


    DROP TABLE IF EXISTS `blob_index`.`blobstore`; 
    CREATE TABLE `blob_index`.`blobstore` (
     `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
     `data` mediumblob NOT NULL, 
     PRIMARY KEY (`id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 

उत्तर

3

मुझे लगता है कि आप खाली मेज पर इस कोशिश कर रहे हैं (क्योंकि MySQL यह पूर्ण तालिका स्कैन करने के लिए एक पंक्ति के माध्यम से जाने की जरूरत है सोचता है), क्या अनुसूचक के परिणामों को प्रभावित कर सकता है:

यहाँ स्कीमा है। जब आप इसे वास्तविक तालिका पर करेंगे, तो EXPLAIN परिणाम भिन्न हो सकते हैं (और वास्तव में मेरे परीक्षण में भिन्नता है)।

+0

आपका अधिकार, मैंने वहां कुछ डेटा फेंक दिया, दोनों टेबलों पर तालिका का विश्लेषण किया, और अब पहली बार मेटा टेबल पर टाइप रेंज का है। – Fredrick

0

यदि मैंने जो लिखा है उसे पढ़ा है तो यह index से ref और eq_ref से all पर जाता है।

CREATE INDEX idx_metadata USING BTREE ON `metadata` (fkBlob,start); 

इसे वापस लेना चाहिए।

3

ऑप्टिमाइज़र सोचता है कि आपको तालिका ऑर्डर को स्वैप करने से लाभ होगा (जिसका अर्थ है कि आंकड़े अद्यतित नहीं हैं)।

आप metadata (start, fkBlob) पर एक सूचकांक से जोड़ने का प्रयास कर सकते हैं:

CREATE INDEX ix_metadata_start_blob ON metadata (start, fkBlob) 

और दोनों टेबल पर ANALYZE TABLE चलाते हैं।

इस प्रकार, start पर सूचकांक metadata पर फ़िल्टर करने के लिए उपयोग किया जाएगा जो अग्रणी बनाया जाएगा। ,

SELECT * 
FROM metadata m 
STRAIGHT_JOIN 
     blobstore b 
ON  b.id = m.fkBlob 
WHERE m.start <= '2009-01-01' 

हालांकि यह आमतौर पर की सिफारिश नहीं कर रहा है:

तुम भी स्पष्ट रूप से शामिल होने के के आदेश मजबूर कर सकते हैं।

0
if the index doesnot take it right use HINTS 

select /* INDEX <index_name> */ 
blah blah blah 
from ........ 
0

पहले उदाहरण में, MySQL मेटाडाटा fk_blob सूचकांक का इस्तेमाल किया है, क्योंकि यह एक कवर सूचकांक था - प्रत्येक स्तंभ आप क्वेरी में उपयोग सूचकांक में उपस्थित थे। (यह "इंडेक्स का उपयोग" का अर्थ है।) उस क्वेरी ने अभी भी एक पूर्ण स्कैन किया है, लेकिन यह प्राथमिक के बजाय द्वितीयक अनुक्रमणिका के माध्यम से प्रत्येक पंक्ति स्कैन किया गया है। जैसे ही आप शुरू करते थे, आप कवरिंग इंडेक्स और MySQL की गणना खो देते थे, यह ड्राइविंग इंडेक्स के रूप में ब्लॉबस्टोर का उपयोग करने के लिए तेज़ था। (InnoDB की प्राथमिक अनुक्रमणिका पंक्ति भंडारण के साथ एकीकृत है।)

यदि आप चाहते हैं कि MySQL ड्राइविंग इंडेक्स के रूप में मेटाडेटा इंडेक्स का उपयोग करना जारी रखे, तो सुनिश्चित करें कि उस पर एक एकल अनुक्रमणिका है जो क्वेरी के लिए उपयोगी होगी। दूसरी क्वेरी के लिए (प्रारंभ, fkBlob) पर एक सूचकांक सबसे अच्छा होगा, लेकिन यह अन्य प्रश्नों के लिए उपयोगी नहीं हो सकता है। अगली सबसे अच्छी अनुक्रमणिका (fkBlob) को प्रतिस्थापित करना है (fkBlob, प्रारंभ)।कुशल क्वेरी योजना बनाम आपको बहुत अधिक इंडेक्स (जो बनाए रखने के लिए महंगी हैं) रखने में संतुलन रखना होगा। टेस्ट, टेस्ट, टेस्ट - और कभी भी अंधेरे से अपने देव डेटाबेस पर समझाओ।

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