किसी क्वेरी को कैसे ऑप्टिमाइज़ किया जाए ताकि वह पहले एक इंडेक्स पर तलाश करे और उसके बाद दूसरा इंडेक्स


12

मेरे पास उपग्रह डेटा से पृथ्वी माप के दो सेट हैं, प्रत्येक समय फ़ील्ड्स (माध्य जूलियन तिथि के लिए mjd) और भूगोल स्थिति (जियोप्वाइंट, स्पेसियल) और मैं दो सेटों के बीच संयोग की तलाश कर रहा हूं, जैसे कि उनका समय एक सीमा से मेल खाता है 3 घंटे (या .125 दिन) और एक दूसरे के 200 किमी के भीतर उनकी दूरी।

मैंने दोनों मेजों और स्थानिक तालिकाओं पर दोनों mjd क्षेत्रों के लिए अनुक्रमित किए हैं।

जब मैं सिर्फ समय की कमी में शामिल होता हूं, तो डेटाबेस 8 सेकंड में 100,000 मैचों की गणना करता है और उस समय के सभी 100,000 मैचों के लिए दूरी की गणना करता है। प्रश्न इस तरह दिखता है:

select top 100000 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
option( table hint ( h, index(ix_MJD) ), table hint( m, index(ix_MJD) ) )

और निष्पादित योजना है:

केवल एमजेड बाधा

जब सॉर्ट किया गया, तो 9 की दूरी 200 किमी से कम थी, इसलिए मैच होते हैं। परेशानी यह है, जब मैं दूरी की बाधा को जोड़ता हूं और इसके बजाय इसे चलाता हूं,

select top 10 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
and h.GeoPoint.STDistance(m.GeoPoint)<200000
option( table hint ( h, index(ix_MJD) ), table hint( m, index(ix_MJD) ) )

यह लंबे समय तक चला जाता है। जाहिर है, 8 सेकंड में, यह 100,000 समय मैच पा सकता था, जिनमें से 9 200 किमी से कम थे, इसलिए ऑप्टिमाइज़र को कुछ उप-इष्टतम की कोशिश करनी चाहिए। योजना दूरियों पर एक फिल्टर के साथ ऊपर के समान दिखती है (मैं अनुमान लगा रहा हूं)।

स्थानिक बाधा के साथ, कोई स्थानिक फ़िल्टर नहीं

मैं इसके साथ स्थानिक सूचकांक के उपयोग को बाध्य कर सकता हूं:

select top 5 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0 
from L2V5.dbo.header h join L2.dbo.MLS_Header m 
on h.GeoPoint.STDistance(m.GeoPoint)<200000
and h.mjd between m.mjd-.125 and m.mjd+.125 
option( table hint ( h, index(ix_MJD), index(ix_GeoPoint) ), table hint( m, index(ix_MJD) ) )

दोनों सूचकांक के साथ दोनों बाधाओं

जिसके बाद 5 मैच खोजने में 3 मिनट लगते हैं।

मैं MJD इंडेक्स का उपयोग करने के लिए क्वेरी ऑप्टिमाइज़र को पहले कैसे बताता हूं, और फिर स्थानिक इंडेक्स सेकंड (या यह है कि यह पहले से क्या कर रहा है) और क्या कोई तरीका है जो मैं यह बताकर मदद कर सकता हूं कि कितने मैचों की उम्मीद है? यदि यह 8 सेकेण्ड में दूरी के साथ 100,000 मैचों की गणना कर सकता है, जिसमें 9 200 किमी के नीचे है, तो क्या स्थानिक सूचकांक के अलावा इसे तेजी से धीमा नहीं करना चाहिए?

किसी भी अन्य सुझावों या विचारों के लिए धन्यवाद।

संपादित करें: इस सवाल का जवाब देने के लिए कि योजना संकेत के बिना कैसी दिखती है, यह (और यह हमेशा के लिए लेता है):

कोई संकेत नहीं

शायद यह भी उल्लेखनीय है कि एक तालिका में लगभग 1M रिकॉर्ड हैं और दूसरे में 8M हैं


यदि आप उन संकेतों को हटाते हैं तो आपकी क्वेरी योजना क्या दिखती है?
ज़ेन

@Zane, मैंने पोस्ट को संपादित किया और नो-हिंट क्वेरी प्लान जोड़ा। यह स्कैच को स्कैन के साथ बदल देता है और समय सारिणी है।
user261963

जवाबों:


6

समस्या यह है कि यह (और स्थानिक इंडेक्स को जानकर, शायद होगा) मान लेंगे कि स्थानिक फिल्टर समय फिल्टर की तुलना में बहुत अधिक चयनात्मक होगा।

लेकिन अगर आपके पास 200 किमी के भीतर कुछ मिलियन रिकॉर्ड हैं, तो यह काफी खराब हो सकता है।

आप इसे 200 किमी के भीतर रिकॉर्ड खोजने के लिए कह रहे हैं, जो कुछ स्थानिक क्रम द्वारा आदेशित डेटा लौटाता है। समय में करीब हैं कि रिकॉर्ड को खोजने का मतलब है हर एक की जाँच करना।

या फिर आप समय के अनुसार रिकॉर्ड ढूंढ रहे हैं, और आपको समय क्रम में परिणाम मिल रहे हैं। फिर, इस सूची को 200 किमी के दायरे में फ़िल्टर करना हर एक की जाँच का विषय है।

यदि आप डेटा को दो श्रेणियों में इस तरह से फ़िल्टर करते हैं, तो एक इंडेक्स का उपयोग करके दूसरा फ़िल्टर लागू करना कठिन हो जाता है। यदि समय फिल्टर एक तंग है तो आप इसे स्थानिक सूचकांक का उपयोग नहीं करने के लिए कह सकते हैं।

यदि दोनों व्यक्तिगत रूप से बड़े हैं, और यह केवल एक साथ है कि वे तंग हैं, तो आपके पास एक अधिक जटिल मुद्दा है, एक जिसे लोगों ने लंबे समय तक हल करने की कोशिश की है, और जिसे 3 डी (और उससे परे) अनुक्रमित द्वारा अच्छी तरह से हल किया जा सकता है अंतरिक्ष। सिवाय इसके कि SQL सर्वर उनके पास नहीं है।

माफ़ करना।

संपादित करें: अधिक जानकारी ...

यह समय सीमाओं को खोजने के लिए एक समान समस्या है जो समय में एक विशेष बिंदु को कवर करती है। जब आप उस बिंदु से पहले शुरू होने वाले रिकॉर्ड की खोज करते हैं, तो आपके पास अंत समय की एक अव्यवस्थित गड़बड़ है - और इसके विपरीत। यदि आप फोन बुक में ऐसे लोगों की तलाश करते हैं जिनके उपनाम F से शुरू होते हैं, तो आप उन लोगों को खोजने की उम्मीद नहीं कर सकते हैं, जिनका पहला नाम R से बहुत आसानी से शुरू होता है। और पहले नाम पर एक सूचकांक भी उसी कारण से मदद नहीं करता है। उस अगले इंडेक्स में चीजें ढूंढना कठिन है जब आपका पहला इंडेक्स एक समानता नहीं है।

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

तो आप एक अजीब स्थिति के साथ छोड़ रहे हैं, मुझे डर है। :(

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

select top 100000 h.Time, m.Time, h.GeoPoint.STDistance(m.GeoPoint)/1000.0
from L2V5.dbo.header h join L2.dbo.MLS_Header m
on h.mjd between m.mjd-.125 and m.mjd+.125
where h.GeoPoint.STDistance(m.GeoPoint)/1000.0 < 200
option( table hint ( h, index(ix_MJD) ) );

ध्यान दें कि मैं जानबूझकर 200 से तुलना करने से पहले 1000 से विभाजित करके व्यंग्यता को तोड़ रहा हूं। मैं चाहता हूं कि यह कार्य मुख्य लुकअप में किया जाए।

ध्यान रहे, आप दोनों ix_MJD अनुक्रमित में जियोकॉइन और समय को शामिल करके लुक्स (और संकेत) की आवश्यकता से बच सकते हैं। यह निश्चित रूप से कुछ गर्मी की योजना से बाहर ले जाएगा।


मुझे नहीं पता कि यह कुछ भी बदलता है, लेकिन समय फ़िल्टर बहुत अधिक चयनात्मक है।
user261963

ठीक। तो क्या सभी समय-मिलान वाली पंक्तियों का पता लगाना और फिर सूचकांक के बिना प्रत्येक स्थान की जांच करना स्वीकार्य है?
रोब फार्ले

... तो फिर योजना आपके मूल की तरह दिखती है, लेकिन एक अतिरिक्त विधेय या फ़िल्टर है।
रॉब फ़र्ले

त्वरित बदलाव के साथ कुछ बदलावों का सुझाव दें। आपको मी के बारे में संकेत देने की जरूरत नहीं है, बस एच। यद्यपि यदि आप स्वैप कर सकते हैं कि आप किसमें 1/8 जोड़ रहे हैं, तो यह सुनिश्चित करने के लिए कि आप छोटी तालिका से स्तंभ को संशोधित कर रहे हैं और उन मानों का उपयोग करके बड़े में तलाश कर रहे हैं, वह भी मदद करेगा। यदि h 8M है और m 1M है, तो BETWEEN को विधेय छोड़ दें, और केवल h के लिए संकेत दें। यदि यह दूसरा तरीका है, तो अपने विधेय और संकेत को बदलें (लेकिन संकेत को बदलने से बेहतर है कि उन स्तंभों को अपने सूचकांक में जोड़ें)।
रॉब फार्ले

सभी तालिका संकेत निकालकर अंत में सबसे अच्छा काम करने के लिए लगता है, जब तक कि मैं मी के बीच एच नहीं करता हूं और चारों ओर अन्य तरीके से नहीं। क्वेरी अब जियोप्वाइंट इंडेक्स का उपयोग बिल्कुल भी नहीं करती है, लेकिन यह वैसे भी कुशलता से उनका उपयोग नहीं कर रहा था। मैंने एमजेडी इंडेक्स में जियोप्वाइंट कॉलम को शामिल किया और इससे काफी मदद मिली। select top 10000 h.Time, m.Time, m.GeoPoint.STDistance(h.GeoPoint), h.mjd-m.mjd from L2V5.dbo.header h join L2.dbo.MLS_Header m on m.GeoPoint.STDistance(h.GeoPoint)<200000 and m.mjd between h.mjd-.125 and h.mjd+.125 order by h.mjd
user261963
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.