SARG कार्डिनैलिटी का अनुमान, फुल-स्कैन क्यों नहीं?


11

पूर्ण-स्कैन क्यों नहीं है (SQL 2008 R2 और 2012 पर)?

परीक्षण डेटा:

DROP TABLE dbo.TestTable
GO  
CREATE TABLE dbo.TestTable
(
   TestTableID INT IDENTITY PRIMARY KEY,
   VeryRandomText VarChar(50),
   VeryRandomText2 VarChar(50)
)
Go
Set NoCount ON
Declare @i int
Set @i = 0
While @i < 10000
Begin
   Insert Into dbo.TestTable(VeryRandomText, VeryRandomText2)
      Values(Cast(Rand()*10000000 as VarChar(50)), Cast(Rand()*10000000 as VarChar(50)));
   Set @i = @i + 1;
End
Go
CREATE Index IX_VeryRandomText On dbo.TestTable
(
    VeryRandomText
)
Go

जब क्वेरी निष्पादित करें:

Select * From dbo.TestTable Where VeryRandomText = N'111' -- bad

चेतावनी प्राप्त करें (जैसा कि अपेक्षित है, क्योंकि nchar डेटा की तुलना varchar कॉलम से करें):

<PlanAffectingConvert ConvertIssue="Cardinality Estimate" Expression="CONVERT_IMPLICIT(nvarchar(50),[DemoDatabase].[dbo].[TestTable].[VeryRandomText],0)" />

लेकिन फिर मैं निष्पादन योजना देखता हूं, और मैं देख सकता हूं, कि यह पूर्ण-स्कैन का उपयोग नहीं कर रहा है जैसा कि मैं उम्मीद करूंगा, लेकिन इसके बजाय सूचकांक की तलाश है।

यहाँ छवि विवरण दर्ज करें

बेशक, यह एक तरह से अच्छा है, क्योंकि इस विशेष मामले में निष्पादन तेजी से होता है जैसे कि पूर्ण स्कैन होगा।

लेकिन मैं यह नहीं समझ सकता कि इस योजना को बनाने के लिए SQL सर्वर कैसे निर्णय लेने के लिए आया था।

इसके अलावा- यदि सर्वर कोलाज सर्वर स्तर और SQL सर्वर कोलाज डेटाबेस स्तर पर विंडोज कॉलेशन होगा, तो यह उसी क्वेरी पर पूर्ण स्कैन का कारण होगा।

जवाबों:


8

विभिन्न डेटाटाइप्स SQL ​​सर्वर के मूल्यों की तुलना करते समय डेटा प्रकार की वरीयता नियमों का पालन करें । चूँकि nvarchar में varchar SQL Server की तुलना में अधिक पूर्वता होती है, इसलिए मूल्यों की तुलना करने से पहले कॉलम डेटा को nvarchar में बदलना होता है। इसका मतलब है कि कॉलम पर एक फ़ंक्शन लागू करना और यह क्वेरी को गैर-सारयोग्य बना देगा।

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

जैसा कि आपने नोट किया है, यह तब काम नहीं करता है जब कॉलम का कोलाजेशन एसक्यूएल कॉलेशन होता है। इसका कारण, मेरा मानना ​​है कि, लेख में पाया जा सकता है कि SQL कोलाज़ की तुलना विंडोज के कोलाज से की जाए

मूल रूप से, एक विंडोज कोलाजेशन varchar और nvarchar के लिए समान एल्गोरिथ्म का उपयोग करता है जहां एक SQL कॉलेरेशन varchar डेटा के लिए एक अलग एल्गोरिथ्म का उपयोग करता है और nvarchar डेटा के लिए Windows collation के समान एल्गोरिथ्म।

इसलिए एक विंडोज कॉलेलेशन के तहत varchar से nvarchar में जाने से एक ही एल्गोरिथ्म का उपयोग किया जाएगा और SQL सर्वर आपके मामले में, varchar SQL collation column index से पंक्तियाँ प्राप्त करने के लिए एक nvarchar शाब्दिक से कई मानों का उत्पादन कर सकता है। हालाँकि, जब varchar कॉलम का कोलाज एक SQL Collation होता है जो कि अलग-अलग एल्गोरिथ्म के कारण संभव नहीं होता है।


अपडेट करें:

खिड़कियों और sql टकराव का उपयोग करते हुए varchar स्तंभों के लिए विभिन्न प्रकार के आदेशों का प्रदर्शन।

एसक्यूएल फिडल

एमएस SQL ​​सर्वर 2014 स्कीमा सेटअप :

create table T(C varchar(10));

insert into T values('a-b'),('aa'),('ac');

क्वेरी 1 :

select C
from T
order by C collate SQL_Latin1_General_CP1_CI_AS;

परिणाम :

|   C |
|-----|
| a-b |
|  aa |
|  ac |

क्वेरी 2 :

select C
from T
order by C collate Latin1_General_100_CI_AS;

परिणाम :

|   C |
|-----|
|  aa |
| a-b |
|  ac |

0

आपको यह याद रखना होगा कि नॉनक्लेस्टेड इंडेक्स के लीफ नोड्स में इंडेक्स पेज होते हैं जिनमें डेटा रो को खोजने के लिए क्लस्टरिंग की या आरआईडी होते हैं।

आपके जहाँ खंड में आप VeryRandomText = N'111'बताएंगे कि जब से VeryRandomText पर एक गैर-संकुल सूचकांक है (बनाएँ सूचकांक गैर-संकुल सूचकांक बनाएगा, जब तक कि आप स्पष्ट रूप से इसे एक क्लस्टर बनाने के लिए नहीं कहेंगे) डेटा खोजने के लिए सबसे सस्ता तरीका यह है कि सूचकांक को खोजने के लिए स्कैन करें और पंक्ति को खोजें। फिर पंक्ति के लिए डेटा प्राप्त करें।

यदि आप एक क्लस्टर इंडेक्स बनाएंगे

CREATE clustered Index IX_VeryRandomText On dbo.TestTable (VeryRandomText)

या VeryRandomText पर एक प्राथमिक कुंजी आपको उस सूचकांक का एक स्कैन मिलेगा।

ऑनलाइन किताबें यहां या यहां देखें: http://www.sqlforge.com/w/Clustered_index,_nonclustered_index,_or_heap


हां, आप जो लिख रहे हैं, उससे मैं वाकिफ हूं। जैसा कि आप देख सकते हैं, TestTableID पर पहले से ही संकुल सूचकांक है। लेकिन बात यह है कि - यदि SQL सर्वर केंट कॉलम डेटा वितरण के आंकड़े (जैसा कि इस मामले में, डेटा प्रकार बेमेल के कारण है कि सभी पंक्ति मूल्य डेटा प्रकार रूपांतरण की आवश्यकता होनी चाहिए) को देखते हैं, तो इसे इस मामले में क्लस्टर इंडेक्स स्कैन का चयन करना चाहिए, न कि सूचकांक की तलाश में। ।
जैनीस जूल

और गैर-क्लस्टर किए गए सूचकांक की तलाश / स्कैन करना हमेशा सस्ता नहीं होता है- जब मान पर्याप्त या गैर कवर सूचकांक नहीं होते हैं, तो इसके बजाय क्लस्टर इंडेक्स स्कैन करना सस्ता हो सकता है।
जैनीस

@ जैनी आपकी स्क्रिप्ट बनाने के लिए इंडेक्स नहीं बना रहा है, जिससे आप ऐसा स्पष्ट सूचकांक नहीं बना पाएंगे जो आपको स्पष्ट रूप से कहना है - वही यदि आप क्वेरी प्लान, इंडेक्स सीक (
नॉनस्टस्टर्ड

"जब आप एक प्राथमिक कुंजी बाधा बनाते हैं, तो स्तंभ या स्तंभों पर एक अद्वितीय क्लस्टर इंडेक्स स्वचालित रूप से बनाया जाता है यदि टेबल पर क्लस्टर इंडेक्स पहले से मौजूद नहीं है और आप एक अद्वितीय गैर-अनुक्रमित इंडेक्स निर्दिष्ट नहीं करते हैं।" msdn.microsoft.com/en-us/library/ms186342.aspx
Jānis
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.