चुनता है मेरे पास एक सारणी है जिसमें बहुत अधिक डेटा है, जहां हम विशेष रूप से date
फ़ील्ड की परवाह करते हैं। इसका कारण यह है कि डेटा वॉल्यूम सिर्फ ~ 30x ऊपर चला गया, और पुराने तरीके जल्द ही अलग हो जाएंगे। क्वेरी मुझे आशा है कि तुम मेरे लिए की जरूरत है अनुकूलित करने में सहायता कर सकते हैं:एक क्वेरी को अनुकूलित करने का प्रयास करना जो 'अनुमानित निकटतम रिकॉर्ड'
- एक (एक CTE आधारित तालिका-मान समारोह द्वारा उत्पन्न)
- तिथियों की सूची लेने के उन तारीखों में से प्रत्येक के लिए एक ही रिकॉर्ड को पुनः प्राप्त
- 'निकटतम' के कुछ परिभाषा
उदाहरण के लिए, के आधार पर वर्तमान तालिका 5 सेकंड में डेटा होता है (+/- एक छोटे से) अंतराल। मुझे उस तालिका का नमूना लेने और रिकॉर्ड प्राप्त करने की आवश्यकता है जो 30 सेकंड अंतराल के करीब आता है।
मेरे पास अभी क्या ठीक है ठीक काम करता है। अगर मैं इसे और अधिक अनुकूलित करने का कोई तरीका हूं तो मैं बस उत्सुक हूं। अगर मैं इसे लिंक से एसक्यूएल में कर सकता हूं, तो यह भी साफ होगा। मुझे मूल्य मानों की मात्रा (~ 2 मिलियन पंक्तियां मिनट) दिए गए इंडेक्स पर सुझावों में भी रूचि है।
declare @st datetime ; set @st = '2012-01-31 05:05:00';
declare @end datetime ; set @end = '2012-01-31 05:10:00';
select distinct
log.* -- id,
from
dbo.fn_GenerateDateSteps(@st, @end, 30) as d
inner join lotsOfLogData log on l.Id = (
select top 1 e.[Id]
from
lotsOfLogData as log -- contains data in 5 second intervals
where
log.stationId = 1000
-- search for dates in a certain range
AND utcTime between DateAdd(s, -10, dt) AND DateAdd(s, 5, dt)
order by
-- get the 'closest'. this can change a little, but will always
-- be based on a difference between the date
abs(datediff(s, dt, UtcTime))
)
-- updated the query to be correct. stadionId should be inside the subquery
lotOfLogData की तालिका संरचना नीचे है। अपेक्षाकृत कुछ स्टेशन आईडी (शायद 50) हैं, लेकिन प्रत्येक के लिए बहुत सारे रिकॉर्ड हैं। जब हम पूछते हैं तो हम स्टेशन आईडी को जानते हैं।
create table ##lotsOfLogData (
Id bigint identity(1,1) not null
, StationId int not null
, UtcTime datetime not null
-- 20 other fields, used for other calculations
)
fn_GenerateDateSteps इस तरह एक डाटासेट देता है, पैरामीटर के लिए दिया:
[DT]
2012-01-31 05:05:00.000
2012-01-31 05:05:30.000
2012-01-31 05:06:00.000
2012-01-31 05:06:30.000 (and so on, every 30 seconds)
मैं यह एक अस्थायी तालिका के साथ साथ ही इस तरह से किया है,, लेकिन वह सिर्फ एक छोटे से बाहर आया थोड़ा और महंगा
declare @dates table (dt datetime, ClosestId bigint);
insert into @dates (dt) select dt from dbo.fn_GenerateDateSteps(@st, @end, 30)
update @dates set closestId = (-- same subquery as above)
select * from lotsOfLogData inner join @dates on Id = ClosestId
संपादित करें: अप फिक्स्ड
गॉट 200K + अब के साथ काम करने पंक्तियों। मैंने दोनों तरीकों की कोशिश की, और क्रॉस एक उचित इंडेक्स के साथ लागू होता है (आईडी/समय + शामिल है (.. सभी कॉलम ...) ने ठीक काम किया। हालांकि, मैंने एक सरल (और मौजूदा) का उपयोग करके शुरू की गई क्वेरी के साथ समाप्त किया। । [आईडी + समय] पर सूचकांक क्यों मुझे लगता है कि एक पर बसे अधिक व्यापक रूप से समझा जा सकता क्वेरी है हो सकता है कि वहाँ अभी भी यह करने के लिए एक बेहतर तरीका है, लेकिन मैं यह नहीं देख सकते हैं:। डी
-- subtree cost (crossapply) : .0808
-- subtree cost (id based) : .0797
-- see above query for what i ended up with
क्रॉस लागू होता है कि मैं स्टेशन/समय पर एक इंडेक्स बनाना चाहता हूं तालिका में * सभी * अन्य डेटा शामिल है। इंडेक्स के बिना, यह नग्न क्वेरी के समान ही चलता है, इसलिए इस मामले में क्रॉस काम नहीं करेगा :) मुझे इसके बारे में भी पता नहीं था, इसलिए धन्यवाद! –
ओह, और मेरे पास उस क्वेरी में एक बग था;) मैं * आवश्यक * स्टेशन को subquery में डालने के लिए आवश्यक हूं क्योंकि अन्यथा मैं किसी भी स्टेशन से मेल खाऊंगा जो कि सीमा में है। ऐसा करने के बाद, उचित सूचकांक का उपयोग किया जाता है और सब कुछ सुपर फास्ट (आईएसएच) –
@AndrewBacker - दूर हो गया लेकिन हमें सूचित रखने के लिए धन्यवाद। –