प्राथमिक कुंजी में निर्दिष्ट क्रमबद्ध क्रम, अभी तक छँटाई का चयन SELECT पर किया जाता है


15

मैं सेंसर डेटा को एक तालिका SensorValues में संग्रहीत कर रहा हूं । तालिका और प्राथमिक कुंजी इस प्रकार है:

CREATE TABLE [dbo].[SensorValues](
  [DeviceId] [int] NOT NULL,
  [SensorId] [int] NOT NULL,
  [SensorValue] [int] NOT NULL,
  [Date] [int] NOT NULL,
CONSTRAINT [PK_SensorValues] PRIMARY KEY CLUSTERED 
(
  [DeviceId] ASC,
  [SensorId] ASC,
  [Date] DESC
) WITH (
    FILLFACTOR=75,
    DATA_COMPRESSION = PAGE,
    PAD_INDEX = OFF,
    STATISTICS_NORECOMPUTE = OFF,
    SORT_IN_TEMPDB = OFF,
    IGNORE_DUP_KEY = OFF,
    ONLINE = OFF,
    ALLOW_ROW_LOCKS = ON,
    ALLOW_PAGE_LOCKS = ON)
  ON [MyPartitioningScheme]([Date])

फिर भी, जब मैं एक विशिष्ट समय के लिए मान्य सेंसर मूल्य का चयन करता हूं, तो निष्पादन योजना मुझे बताती है कि यह एक प्रकार कर रहा है। ऐसा क्यों है?

मुझे लगता था कि चूंकि मैं दिनांक कॉलम द्वारा छांटे गए मूल्यों को संग्रहीत करता हूं, इसलिए छंटाई नहीं होगी। या यह इसलिए है क्योंकि सूचकांक केवल दिनांक कॉलम द्वारा सॉर्ट नहीं किया गया है, अर्थात यह नहीं मान सकता कि परिणाम सेट को क्रमबद्ध किया गया है?

SELECT TOP 1 SensorValue
  FROM SensorValues
  WHERE SensorId = 53
    AND DeviceId = 3819
    AND Date < 1339225010
  ORDER BY Date DESC

निष्पादन योजना

संपादित करें: क्या मैं इसके बजाय ऐसा कर सकता हूं?

चूंकि तालिका में DeviceId, SensorId, Date छांटा गया है और मैं केवल एक DeviceId और एक SensorId का चयन करते हुए चयन करता हूं , इसलिए आउटपुट सेट पहले से ही दिनांक DESC द्वारा क्रमबद्ध होना चाहिए । इसलिए मुझे आश्चर्य है कि यदि निम्नलिखित प्रश्न सभी मामलों में समान परिणाम प्राप्त करेंगे?

SELECT TOP 1 SensorValue
  FROM SensorValues
  WHERE SensorId = 53
    AND DeviceId = 3819
    AND Date < 1339225010

नीचे @Catcall के अनुसार, सॉर्ट ऑर्डर स्टोरेज ऑर्डर के समान नहीं है। यानी हम यह नहीं मान सकते कि लौटे मान पहले से ही एक क्रमबद्ध क्रम में हैं।

संपादित करें: मैंने इस क्रॉस एपीपीएलवाई समाधान की कोशिश की है, कोई भाग्य नहीं

@ मर्टिन स्मिथ ने सुझाव दिया कि मैं विभाजन के खिलाफ अपने परिणाम को लागू करने की कोशिश करूंगा। मुझे इसी तरह की समस्या का वर्णन करते हुए एक ब्लॉग पोस्ट ( विभाजन तालिका पर गैर-क्लस्टर किए गए अनुक्रमणिकाएं ) मिलीं और स्मिथ ने जो सुझाव दिया, उसके समान समाधान का प्रयास किया। हालांकि, यहां कोई किस्मत नहीं, निष्पादन समय मेरे मूल समाधान के बराबर है।

WITH Boundaries(boundary_id)
AS
(
  SELECT boundary_id
  FROM sys.partition_functions pf
  JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
  WHERE pf.name = 'PF'
  AND prf.value <= 1339225010
  UNION ALL
  SELECT max(boundary_id) + 1
  FROM sys.partition_functions pf
  JOIN sys.partition_range_values prf ON pf.function_id = prf.function_id
  WHERE pf.name = 'PF'
  AND prf.value <= 1339225010
),
Top1(SensorValue)
AS
(
  SELECT TOP 1 d.SensorValue
  FROM Boundaries b
  CROSS APPLY
  (
    SELECT TOP 1 SensorValue
      FROM SensorValues
      WHERE  SensorId = 53
        AND DeviceId = 3819
        AND "Date" < 1339225010
        AND $Partition.PF(Date) = b.boundary_id
        ORDER BY Date DESC
  ) d
  ORDER BY d.Date DESC
)
SELECT SensorValue
FROM Top1

विकल्प MAXDOP 1 मदद नहीं करता है। जैसा कि @Martin Smith द्वारा नीचे दिया गया है, ऐसा लगता है कि विभाजन के कारण क्या है ...
m__

जवाबों:


13

गैर-विभाजित तालिका के लिए मुझे निम्नलिखित योजना मिलती है

योजना 1

पर एक ही तलाश है Seek Keys[1]: Prefix: DeviceId, SensorId = (3819, 53), Start: Date < 1339225010

इसका मतलब है कि SQL सर्वर पहले दो स्तंभों पर एक समानता की तलाश कर सकता है और फिर एक रेंज शुरू करना शुरू कर सकता है 1339225010और आदेश दिया जा सकता है FORWARD(जैसे कि सूचकांक परिभाषित किया गया है [Date] DESC)

TOPतलाश से के बाद पहली पंक्ति उत्सर्जित होता है ऑपरेटर अधिक पंक्तियों का अनुरोध बंद हो जाएगा।

जब मैं विभाजन योजना और फ़ंक्शन बनाता हूं

CREATE PARTITION FUNCTION PF (int)
AS RANGE LEFT FOR VALUES (1000, 1339225009 ,1339225010 , 1339225011);
GO
CREATE PARTITION SCHEME [MyPartitioningScheme]
AS PARTITION PF
ALL TO ([PRIMARY] );

और निम्न डेटा के साथ तालिका को आबाद करें

INSERT INTO [dbo].[SensorValues]    
/*500 rows matching date and SensorId, DeviceId predicate*/
SELECT TOP (500) 3819,53,1, ROW_NUMBER() OVER (ORDER BY (SELECT 0))           
FROM master..spt_values
UNION ALL
/*700 rows matching date but not SensorId, DeviceId predicate*/
SELECT TOP (700) 3819,52,1, ROW_NUMBER() OVER (ORDER BY (SELECT 0))           
FROM master..spt_values
UNION ALL 
/*1100 rows matching SensorId, DeviceId predicate but not date */
SELECT TOP (1100) 3819,53,1, ROW_NUMBER() OVER (ORDER BY (SELECT 0)) + 1339225011      
FROM master..spt_values

SQL Server 2008 पर योजना निम्नानुसार है।

योजना २

साधक की उत्सर्जित पंक्तियों की वास्तविक संख्या है 500। योजना से पता चलता है कि विधेय की तलाश है

Seek Keys[1]: Start: PtnId1000 <= 2, End: PtnId1000 >= 1, 
Seek Keys[2]: Prefix: DeviceId, SensorId = (3819, 53), Start: Date < 1339225010

यह इंगित करते हुए यहां बताए गए स्किप स्कैन दृष्टिकोण का उपयोग कर रहा है

क्वेरी ऑप्टिमाइज़र को विस्तारित किया जाता है, ताकि एक स्थिति के साथ एक खोज या स्कैन ऑपरेशन पार्टीशनआईडी (तार्किक अग्रणी स्तंभ के रूप में) और संभवत: अन्य सूचकांक कुंजी स्तंभों पर किया जा सके, और फिर एक दूसरे स्तर की तलाश, एक अलग स्थिति के साथ किया जा सकता है। एक या अधिक अतिरिक्त स्तंभों पर, प्रत्येक अलग-अलग मूल्य के लिए जो पहले स्तर के तलाश ऑपरेशन के लिए योग्यता को पूरा करता है।

यह योजना एक सीरियल प्लान है और इसलिए विशिष्ट क्वेरी के लिए आपको ऐसा लगता है कि यदि SQL सर्वर ने यह सुनिश्चित कर लिया है कि यह विभाजन को इस क्रम में संसाधित करता है dateकि मूल योजना TOPअभी भी काम करेगी और यह पहली मिलान पंक्ति के बाद प्रसंस्करण को रोक सकती है शेष 499 मैचों को जारी रखने और आउटपुट करने के बजाय पाया गया।

वास्तव में 2005 की योजना यह देखती है कि यह उस दृष्टिकोण को अपनाती है

2005 की योजना

मुझे यकीन नहीं है कि अगर यह 2008 की योजना को प्राप्त करने के लिए सीधे आगे है या शायद इसे अनुकरण करने के लिए इस OUTER APPLYपर आवश्यकता होगी sys.partition_range_values



9

बहुत सारे लोग मानते हैं कि एक संकुल सूचकांक आउटपुट पर क्रमबद्ध क्रम की गारंटी देता है । लेकिन ऐसा नहीं है कि यह क्या करता है; यह डिस्क पर स्टोरेज ऑर्डर की गारंटी देता है ।

उदाहरण के लिए, इस ब्लॉग पोस्ट और इस लंबी चर्चा को देखें


1
ठीक है, पहले, ओपी ने यह भी कहा, "मैंने सोचा होगा कि चूंकि मैं दिनांक स्तंभ द्वारा छाँटे गए मूल्यों को संग्रहीत करता हूं, इसलिए छंटाई नहीं होगी [sic]।" तो समस्या का कम से कम हिस्सा यह है कि एक गुच्छेदार सूचकांक क्या करता है के बारे में गलत धारणा। मुझे लगता है कि वैसे भी इसे सीधा करना अच्छा है।
माइक शेरिल 'कैट रिकॉल'

शायद मैं सिर्फ जिद्दी हो रहा हूं (इसलिए मुझे माफ कर दो ;-))। किसी भी तरह, मैंने ह्यूगो कोर्नेलिस द्वारा ब्लॉग पोस्ट पढ़ा है और यह बहुत सीधे आगे है। हालांकि, उनके उदाहरण में वह एक संकुल सूचकांक और एक गैर-संकुल का उपयोग कर रहा है, गैर-संकुल सूचकांक आकार में छोटा है और इसलिए निष्पादन योजना में इसका उपयोग किया जा रहा है। मेरे मामले में मेरे पास केवल एक संकुल सूचकांक है, क्या SQL सर्वर अभी भी गलत क्रम में मान लौटा सकता है (इसका उपयोग करने के लिए कोई छोटा सूचकांक नहीं है और पूर्ण टेबल स्कैन बहुत धीमी गति से होता है)?
m__

मैंने इसे एक नए प्रश्न (विषय से दूर) में स्थानांतरित कर दिया है
m__

5

मैं अनुमान लगा रहा हूं कि समानांतर योजना के कारण SORT की आवश्यकता है। मैं इसे कुछ मंद और दूर के ब्लॉग लेख पर आधारित करता हूं: लेकिन मैंने इसे MSDN पर पाया, जो इसे उचित ठहरा सकता है या नहीं

तो, MAXDOP 1 के साथ प्रयास करें और देखें कि क्या होता है ...

मुझे लगता है कि "एक्सचेंज ऑपरेटर" के तहत सिंपल टॉक पर @sql kiwi के ब्लॉग पोस्ट में संकेत दिया गया है। और यहां "डीओपी निर्भरता"


हालांकि मैंने dateइससे पहले विभाजन कार्य को स्थापित करने की जहमत नहीं उठाई थी । अब मेरे पास है और लगता है कि विभाजन 2005 का अपराधी है जो संभवतः इस विशेष क्वेरी के लिए बेहतर व्यवहार कर रहा है।
मार्टिन स्मिथ

1

मूल रूप से आप सही हैं - चूंकि प्राथमिक कुंजी "DeviceId, SensorId, Date" क्रम में है, इसलिए कुंजी में डेटा दिनांक द्वारा सॉर्ट नहीं किया गया है, इसलिए इसका उपयोग नहीं किया जा सकता है। यदि आपकी कुंजी एक अलग क्रम "तिथि, DeviceId, SensorId" में थी, तो कुंजी में डेटा तिथि के अनुसार क्रमबद्ध होगा , इसलिए इसका उपयोग किया जा सकता है ...


मैंने पहले ही आपके द्वारा बताए गए तरीके को बदलने की कोशिश की थी, इसलिए मुझे खेद नहीं है। वैसे भी, सभी 3 कॉलमों पर गैर-संकुलित सूचकांक बनाने की कोशिश करेंगे और देखें कि इससे मुझे क्या मिलता है। (लापता सूचकांक की खोज जारी है ... ;-))
m__
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.