मेरे पास एक क्वेरी है जो पैरामीटर के रूप में एक json स्ट्रिंग लेता है। Json अक्षांश, देशांतर जोड़े का एक सरणी है। एक उदाहरण इनपुट निम्नलिखित हो सकता है।
declare @json nvarchar(max)= N'[[40.7592024,-73.9771259],[40.7126492,-74.0120867]
,[41.8662374,-87.6908788],[37.784873,-122.4056546]]';
यह एक टीवीएफ कहता है जो 1,3,5,10 मील की दूरी पर एक भौगोलिक बिंदु के आसपास POI की संख्या की गणना करता है।
create or alter function [dbo].[fn_poi_in_dist](@geo geography)
returns table
with schemabinding as
return
select count_1 = sum(iif(LatLong.STDistance(@geo) <= 1609.344e * 1,1,0e))
,count_3 = sum(iif(LatLong.STDistance(@geo) <= 1609.344e * 3,1,0e))
,count_5 = sum(iif(LatLong.STDistance(@geo) <= 1609.344e * 5,1,0e))
,count_10 = count(*)
from dbo.point_of_interest
where LatLong.STDistance(@geo) <= 1609.344e * 10
Json क्वेरी का आशय इस फ़ंक्शन को बल्क कॉल करना है। अगर मैं इसे इस तरह कहता हूं तो प्रदर्शन केवल 4 सेकंड के लिए लगभग 10 सेकंड ले रहा है:
select row=[key]
,count_1
,count_3
,count_5
,count_10
from openjson(@json)
cross apply dbo.fn_poi_in_dist(
geography::Point(
convert(float,json_value(value,'$[0]'))
,convert(float,json_value(value,'$[1]'))
,4326))
योजना = https://www.brentozar.com/pastetheplan/?id=HJDCYd_o4
हालांकि, एक व्युत्पन्न तालिका के अंदर भूगोल के निर्माण को स्थानांतरित करने से प्रदर्शन में सुधार होता है, जिससे क्वेरी लगभग 1 सेकंड में पूरी होती है।
select row=[key]
,count_1
,count_3
,count_5
,count_10
from (
select [key]
,geo = geography::Point(
convert(float,json_value(value,'$[0]'))
,convert(float,json_value(value,'$[1]'))
,4326)
from openjson(@json)
) a
cross apply dbo.fn_poi_in_dist(geo)
योजना = https://www.brentozar.com/pastetheplan/?id=HkSS5_OoE
योजनाएं लगभग समान दिखती हैं। न तो समानता का उपयोग करता है और दोनों स्थानिक सूचकांक का उपयोग करते हैं। धीमी योजना पर एक अतिरिक्त आलसी स्पूल है जिसे मैं संकेत के साथ समाप्त कर सकता हूं option(no_performance_spool)
। लेकिन क्वेरी प्रदर्शन नहीं बदलता है। यह अभी भी बहुत धीमा है।
एक बैच में जोड़े गए संकेत के साथ दोनों को चलाने से दोनों प्रश्नों का समान रूप से वजन होगा।
Sql सर्वर संस्करण = Microsoft SQL Server 2016 (SP1-CU7-GDR) (KB4057119) - 13.0.4466.4 (X64)
तो मेरा सवाल यह है कि यह मामला क्यों है? मुझे कैसे पता चलेगा कि मुझे किसी व्युत्पन्न तालिका के अंदर मूल्यों की गणना करनी चाहिए या नहीं?
point_of_interest
टेबल पर 358306 लॉजिकल पढ़ते हैं , दोनों इंडेक्स 4602 बार स्कैन करते हैं, और दोनों एक काम करने योग्य और वर्कफ़ाइल उत्पन्न करते हैं। आकलनकर्ता का मानना है कि ये योजनाएं समान हैं, फिर भी प्रदर्शन अन्यथा कहते हैं।
|LatLong.Lat - @geo.Lat| + |LatLong.Long - @geo.Long| < n
आप अधिक जटिल करने से पहले मूल्य रखते हैं sqrt((LatLong.Lat - @geo.Lat)^2 + (LatLong.Long - @geo.Long)^2)
। और इससे भी बेहतर, पहले ऊपरी और निचले सीमा की गणना करें, फिर LatLong.Lat > @geoLatLowerBound && LatLong.Lat < @geoLatUpperBound && LatLong.Long > @geoLongLowerBound && LatLong.Long < @geoLongUpperBound
। (यह स्यूडोकोड है, उचित रूप से अनुकूलित करें।)