EXPLAIN
. के आधार पर आपके प्रश्न में आउटपुट, आपके पास पहले से ही सभी इंडेक्स हैं जो क्वेरी चाहिए का उपयोग कर रहे हैं, अर्थात्:
CREATE INDEX idx_zip_from_distance
ON zipcode_distances (zipcode_from, distance, zipcode_to);
CREATE INDEX idx_zipcode ON venues (zipcode, id);
CREATE INDEX idx_venue_id ON events (venue_id);
(मैं आपके सूचकांक नामों से निश्चित नहीं हूं कि idx_zip_from_distance
वास्तव में zipcode_to
. शामिल है कॉलम। अगर नहीं, तो आपको इसे कवरिंग इंडेक्स बनाने के लिए जोड़ना चाहिए
. साथ ही, मैंने venues.id
. शामिल किया है idx_zipcode
में कॉलम पूर्णता के लिए, लेकिन, यह मानते हुए कि यह तालिका के लिए प्राथमिक कुंजी है और आप InnoDB का उपयोग कर रहे हैं, इसे वैसे भी स्वचालित रूप से शामिल किया जाएगा।)
हालांकि, ऐसा लगता है कि MySQL एक अलग, और संभवतः उप-इष्टतम, क्वेरी योजना चुन रहा है, जहां यह सभी घटनाओं के माध्यम से स्कैन करता है, उनके स्थान और ज़िप कोड ढूंढता है, और उसके बाद ही दूरी पर परिणामों को फ़िल्टर करता है। यह सकता इष्टतम क्वेरी योजना बनें, यदि ईवेंट तालिका की कार्डिनैलिटी काफी कम थी, लेकिन इस तथ्य से कि आप यह प्रश्न पूछ रहे हैं, मुझे लगता है कि यह नहीं है।
उप-इष्टतम क्वेरी योजना का एक कारण कर सकता था तथ्य यह है कि आपके पास बहुत अधिक है सूचकांक जो योजनाकार को भ्रमित कर रहे हैं। उदाहरण के लिए, क्या आप सच में ज़िपकोड तालिका पर उन सभी तीन अनुक्रमणिकाओं की आवश्यकता है, यह देखते हुए कि यह जो डेटा संग्रहीत करता है वह संभवतः सममित है? व्यक्तिगत रूप से, मैं केवल ऊपर वर्णित अनुक्रमणिका, साथ ही (zipcode_to, zipcode_from)
पर एक अद्वितीय अनुक्रमणिका (जो कि प्राथमिक कुंजी भी हो सकती है, यदि आपके पास कोई कृत्रिम कुंजी नहीं है) का सुझाव दूंगा। (अधिमानतः उस क्रम में, ताकि zipcode_to=?
. पर कभी-कभार कोई पूछताछ हो सके इसका उपयोग कर सकते हैं)।
हालांकि, मेरे द्वारा किए गए कुछ परीक्षणों के आधार पर, मुझे मुख्य समस्या पर संदेह है कि MySQL गलत क्वेरी योजना क्यों चुन रहा है, यह आपकी तालिकाओं की सापेक्ष कार्डिनैलिटी पर आता है। संभवतः, आपका वास्तविक zipcode_distances
तालिका विशाल है , और MySQL इतना स्मार्ट नहीं है कि यह समझ सके कि WHERE
. में स्थितियां कितनी हैं खंड वास्तव में इसे कम करता है।
यदि ऐसा है, तो सबसे अच्छा और सरल समाधान केवल force करना हो सकता है। MySQL अपनी इच्छित अनुक्रमणिका का उपयोग करने के लिए :
select
*
from
zipcode_distances z
FORCE INDEX (idx_zip_from_distance)
inner join
venues v
FORCE INDEX (idx_zipcode)
on z.zipcode_to=v.zipcode
inner join
events e
FORCE INDEX (idx_venue_id)
on v.id=e.venue_id
where
z.zipcode_from='92108' and
z.distance <= 5
उस प्रश्न के साथ, आपको वास्तव में वांछित क्वेरी योजना मिलनी चाहिए। (आपको FORCE INDEX
की जरूरत है यहाँ, चूंकि केवल USE INDEX
. के साथ क्वेरी प्लानर अभी भी उद्देश्य को हराने, सुझाए गए इंडेक्स के बजाय टेबल स्कैन का उपयोग करने का निर्णय ले सकता है। मैंने ऐसा तब किया था जब मैंने पहली बार इसका परीक्षण किया था।)
पी.एस. यहां SQLize पर एक डेमो दिया गया है, दोनों साथ
और बिना
FORCE INDEX
, इस मुद्दे को प्रदर्शित करते हुए।