एक तालिका चर पर एक सूचकांक बनाना


189

क्या आप SQL Server 2000 में टेबल वेरिएबल पर एक इंडेक्स बना सकते हैं?

अर्थात

DECLARE @TEMPTABLE TABLE (
     [ID] [int] NOT NULL PRIMARY KEY
    ,[Name] [nvarchar] (255) COLLATE DATABASE_DEFAULT NULL 
)

क्या मैं एक सूचकांक बना सकता हूँ Name?


3
दोनों प्रकार के अस्थायी तालिकाओं को बनाने में एक लागत है; और यदि आपके पास इतना डेटा है कि आपको एक सूचकांक की आवश्यकता है तो यह एक वास्तविक तालिका का उपयोग करने का समय हो सकता है; कि आप सुरक्षित लेनदेन करने के लिए सेट अप करें; स्पिड या यूजर आईडी द्वारा फ़िल्टर करें और फिर इसे अंत में साफ़ करें। असली तालिकाओं v अस्थायी तालिकाओं में दोनों में उतार-चढ़ाव होते हैं लेकिन यदि प्रदर्शन एक मुद्दा है; इसे एक वास्तविक तालिका के साथ भी आज़माएं।
u07ch

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

@bielawski यह एक टेबल वैरिएबल है न कि टेम्प टेबल। तालिका चर स्पष्ट रूप से नामित बाधाओं की अनुमति नहीं देते हैं, सिस्टम उत्पन्न नाम अद्वितीय होने की गारंटी है। वे 2014 से नामांकित अनुक्रमित की अनुमति देते हैं, लेकिन यह एक समस्या नहीं है क्योंकि अनुक्रमित को केवल ऑब्जेक्ट के भीतर विशिष्ट रूप से नामित करने की आवश्यकता होती है, वस्तुओं में नहीं।
मार्टिन स्मिथ

मेरी बात 2 गुना थी। 1) लेनदेन के उलझाव से बचने के लिए एक चर का उपयोग करने के अलावा अन्य कोई अस्थायी तालिका और तालिका चर के बीच कोई भौतिक अंतर नहीं है। V-2000 में हालांकि एक चर के लिए बाधाओं, अनुक्रमित ... को जोड़ने के लिए कोई वाक्यविन्यास नहीं है। 2) यह देखते हुए कि कोई एक अस्थायी तालिका का उपयोग कर सकता है, नामित तालिका उपांगों जैसे कि एक ही एसपी की प्रतियों को निष्पादित करने के साथ-साथ एक स्थैतिक नाम का उपयोग करने पर संघर्ष होगा ! नीचे दिए गए तंत्र को स्पष्ट रूप से विकसित किया गया था क्योंकि मैंने सपा को इन सटीक परिस्थितियों के दौरान अनुक्रमित होने वाले अनुक्रमित नामित करने में विफलताओं का पता लगाया था। वे अद्वितीय होना चाहिए।
बिलावस्की 13

1
@bielawski - कोई इंडेक्स नाम वस्तुओं के बीच अद्वितीय होने की आवश्यकता नहीं है - केवल बाधा वाले नाम करते हैं। यह परीक्षण करने के लिए तुच्छ है। बस निष्पादित करेंCREATE TABLE #T1(X INT); CREATE TABLE #T2(X INT); CREATE INDEX IX ON #T1(X); CREATE INDEX IX ON #T2(X);
मार्टिन स्मिथ

जवाबों:


362

प्रश्न SQL Server 2000 को टैग किया गया है, लेकिन नवीनतम संस्करण पर विकसित लोगों के लाभ के लिए मैं इसे पहले संबोधित करूंगा।

SQL सर्वर 2014

SQL सर्वर 2014 के नीचे चर्चा की गई बाधा आधारित इंडेक्स को जोड़ने के तरीकों के अलावा, गैर-अनूठे इंडेक्स को टेबल चर घोषणाओं पर इनलाइन सिंटैक्स के साथ सीधे निर्दिष्ट करने की अनुमति देता है।

उसके लिए उदाहरण वाक्य रचना नीचे है।

/*SQL Server 2014+ compatible inline index syntax*/
DECLARE @T TABLE (
C1 INT INDEX IX1 CLUSTERED, /*Single column indexes can be declared next to the column*/
C2 INT INDEX IX2 NONCLUSTERED,
       INDEX IX3 NONCLUSTERED(C1,C2) /*Example composite index*/
);

शामिल किए गए स्तंभों के साथ फ़िल्टर्ड इंडेक्स और इंडेक्स वर्तमान में इस सिंटैक्स के साथ घोषित नहीं किए जा सकते हैं, हालांकि SQL Server 2016 इसे थोड़ा और आराम देता है। CTP 3.1 से अब टेबल वेरिएबल्स के लिए फ़िल्टर्ड इंडेक्स घोषित करना संभव है। आरटीएम द्वारा यह ऐसा मामला हो सकता है जिसमें स्तंभों को भी शामिल किया गया है, लेकिन वर्तमान स्थिति यह है कि वे "संभवतः संसाधन बाधाओं के कारण इसे SQL16 में नहीं बनाएंगे"

/*SQL Server 2016 allows filtered indexes*/
DECLARE @T TABLE
(
c1 INT NULL INDEX ix UNIQUE WHERE c1 IS NOT NULL /*Unique ignoring nulls*/
)

SQL सर्वर 2000 - 2012

क्या मैं नाम पर एक सूचकांक बना सकता हूं?

संक्षिप्त उत्तर: हां।

DECLARE @TEMPTABLE TABLE (
  [ID]   [INT] NOT NULL PRIMARY KEY,
  [Name] [NVARCHAR] (255) COLLATE DATABASE_DEFAULT NULL,
  UNIQUE NONCLUSTERED ([Name], [ID]) 
  ) 

एक अधिक विस्तृत जवाब नीचे है।

SQL सर्वर में पारंपरिक तालिकाओं में या तो संकुल अनुक्रमणिका हो सकती है या उन्हें ढेर के रूप में संरचित किया जाता है ।

क्लस्टर इंडेक्स या तो डुप्लिकेट कुंजी मान को अस्वीकार करने के लिए या गैर अद्वितीय के लिए डिफ़ॉल्ट के रूप में घोषित किए जा सकते हैं। नहीं अनूठा तो एसक्यूएल सर्वर चुपचाप एक जोड़ता है, तो uniqueifier उन्हें अद्वितीय बनाने के लिए किसी भी डुप्लिकेट चाबी है।

गैर-संकुलित सूचकांक को भी स्पष्ट रूप से अद्वितीय घोषित किया जा सकता है। अन्यथा नॉन यूनिक केस के लिए SQL Server सभी इंडेक्स कीज़ (न केवल डुप्लिकेट्स) के लिए पंक्ति लोकेटर (क्लस्टर इंडेक्स की या RID को ढेर के लिए) जोड़ता है, यह फिर से सुनिश्चित करता है कि वे अद्वितीय हैं।

SQL सर्वर 2000 - 2012 में तालिका चर पर अनुक्रमित केवल एक UNIQUEया PRIMARY KEYबाधा बनाकर निहित किया जा सकता है । इन बाधा प्रकारों के बीच अंतर यह है कि प्राथमिक कुंजी गैर अशक्त स्तंभ (ओं) पर होनी चाहिए। एक अद्वितीय बाधा में भाग लेने वाले स्तंभ अशक्त हो सकते हैं। (हालांकि एस की मौजूदगी में एसक्यूएल सर्वर के अनूठे अवरोधों का कार्यान्वयन NULLएसक्यूएल स्टैंडर्ड में निर्दिष्ट प्रति के अनुसार नहीं है)। इसके अलावा एक टेबल में केवल एक प्राथमिक कुंजी लेकिन कई अद्वितीय बाधाएं हो सकती हैं।

इन दोनों तार्किक बाधाओं को शारीरिक रूप से एक अद्वितीय सूचकांक के साथ लागू किया जाता है। यदि स्पष्ट रूप से निर्दिष्ट नहीं किया PRIMARY KEYगया है, तो संकुल अनुक्रमणिका बन जाएगी और अद्वितीय अवरोध गैर-संकुल हो जाएंगे, लेकिन इस व्यवहार को स्पष्ट रूप से निर्दिष्ट करने CLUSTEREDया NONCLUSTEREDबाधा घोषणा के साथ ओवरराइड किया जा सकता है (उदाहरण वाक्य रचना)

DECLARE @T TABLE
(
A INT NULL UNIQUE CLUSTERED,
B INT NOT NULL PRIMARY KEY NONCLUSTERED
)

उपरोक्त के परिणामस्वरूप निम्न अनुक्रमणिका को SQL Server 2000 - 2012 में तालिका चर पर बनाया जा सकता है।

+-------------------------------------+-------------------------------------+
|             Index Type              | Can be created on a table variable? |
+-------------------------------------+-------------------------------------+
| Unique Clustered Index              | Yes                                 |
| Nonunique Clustered Index           |                                     |
| Unique NCI on a heap                | Yes                                 |
| Non Unique NCI on a heap            |                                     |
| Unique NCI on a clustered index     | Yes                                 |
| Non Unique NCI on a clustered index | Yes                                 |
+-------------------------------------+-------------------------------------+

पिछले एक स्पष्टीकरण की आवश्यकता है। इस उत्तर की शुरुआत में तालिका चर परिभाषा में गैर अद्वितीय गुच्छेदार सूचकांक पर Nameएक अद्वितीय सूचकांक द्वारा अनुकरण किया जाता है Name,Id(याद रखें कि SQL सर्वर चुपचाप गैर अद्वितीय NCI कुंजी के लिए संकुल सूचकांक कुंजी जोड़ देगा)।

एक अनूठे क्लस्टर्ड इंडेक्स IDENTITYको एक यूनीकफायर के रूप में कार्य करने के लिए मैन्युअल रूप से एक कॉलम जोड़कर भी प्राप्त किया जा सकता है ।

DECLARE @T TABLE
(
A INT NULL,
B INT NULL,
C INT NULL,
Uniqueifier INT NOT NULL IDENTITY(1,1),
UNIQUE CLUSTERED (A,Uniqueifier)
)

लेकिन यह एक सटीक सिमुलेशन नहीं है कि एक गैर अद्वितीय क्लस्टर इंडेक्स सामान्य रूप से वास्तव में SQL सर्वर में कैसे लागू किया जाएगा क्योंकि यह "अद्वितीय" सभी पंक्तियों में जोड़ता है। सिर्फ वे ही नहीं जिनकी आवश्यकता है।


1
नोट: 2000-2012 समाधान केवल तभी काम करता है जब टेक्स्ट कॉलम <= 900 बाइट्स। अर्थात। varchar (900), nvarchar (450)
आंद्रे Figueiredo

1
@AndreFigueiredo हां, यह उन संस्करणों में भी स्थायी तालिकाओं पर एक सूचकांक कुंजी के लिए अधिकतम आकार है।
मार्टिन स्मिथ

1
मैं सिर्फ यह नोट करना चाहता था कि एसक्यूएल 2014 का जवाब अज़ूर में अच्छा काम करता है। धन्यवाद मार्टिन!
१२:२० बजे जैक्सिडियन

13

यह समझा जाना चाहिए कि एक प्रदर्शन के दृष्टिकोण से @temp तालिकाओं और #temp तालिकाओं के बीच कोई अंतर नहीं है जो चर का पक्ष लेते हैं। वे एक ही जगह (टेम्पर्ड) में रहते हैं और उसी तरह लागू होते हैं। सभी अंतर अतिरिक्त सुविधाओं में दिखाई देते हैं। इसे आश्चर्यजनक रूप से पूरा लिखें: /dba/16385/whats-the-difference-between-a-temp-table-and-table-variable-in-sll-server/16386#16386

हालांकि ऐसे मामले हैं जहां एक अस्थायी तालिका का उपयोग तालिका या स्केलर फ़ंक्शन के रूप में नहीं किया जा सकता है, v2016 से पहले अधिकांश मामलों के लिए (जहां फ़िल्टर किए गए अनुक्रमित को एक तालिका चर में जोड़ा जा सकता है) आप बस एक # तालिका का उपयोग कर सकते हैं।

Tempdb में नामित अनुक्रमित (या बाधाओं) का उपयोग करने का दोष यह है कि नाम तब टकरा सकते हैं। न केवल सैद्धांतिक रूप से अन्य प्रक्रियाओं के साथ, बल्कि अक्सर प्रक्रिया के अन्य उदाहरणों के साथ आसानी से जो कि #temp तालिका की अपनी प्रतिलिपि पर एक ही सूचकांक डालने की कोशिश करेंगे।

नाम की गड़बड़ी से बचने के लिए, ऐसा कुछ आमतौर पर काम करता है:

declare @cmd varchar(500)='CREATE NONCLUSTERED INDEX [ix_temp'+cast(newid() as varchar(40))+'] ON #temp (NonUniqueIndexNeeded);';
exec (@cmd);

यह एक ही प्रक्रिया के एक साथ निष्पादित होने के बीच भी नाम हमेशा अद्वितीय है।


इसमें
विचर

1
नामांकित अनुक्रमित के साथ कोई समस्या नहीं है - अनुक्रमित को केवल एक तालिका के भीतर विशिष्ट नाम देना होगा। समस्या नामित बाधाओं के साथ है और सबसे अच्छा समाधान आम तौर पर उन्हें अस्थायी तालिकाओं में नाम नहीं देना है - नामित बाधाएं अस्थायी तालिका ऑब्जेक्ट कैशिंग को रोकती हैं।
मार्टिन स्मिथ

1
यह केवल कुछ संस्करणों के लिए सही होना चाहिए (यदि यह किसी भी संस्करण के लिए सही है)। मुझे विशेष रूप से इस वर्कअराउंड के साथ आना पड़ा क्योंकि मैंने एक साथ निष्पादन के दौरान नाम अनुक्रमितों के टकराव को विफल कर दिया।
बिलावस्की

@bielawski क्या आप 2016 का उपयोग कर रहे हैं? मैं इस बात को लेकर बहुत उत्सुक हूं कि टेम्प टेबलों पर नामांकित सूचकांक समवर्ती वातावरण के लिए जोखिम हैं।
इलास्कानेर

1
@Elaskanator हाँ, वे हैं। हमें लोड के तहत एसक्यूएल मेटा डेटा टेबल में विवाद देखने को मिला, जिससे इंडेक्स का नाम हटाकर समस्या का समाधान हो गया। यह एसक्यूएल 2016 था।
डैन डेफ

0

यदि टेबल वेरिएबल में बड़ा डेटा है, तो टेबल वेरिएबल (@table) के बजाय temp टेबल (#table) बनाएं। .table वेरिएबल डालने के बाद इंडेक्स बनाने की अनुमति नहीं देता है।

 CREATE TABLE #Table(C1 int,       
  C2 NVarchar(100) , C3 varchar(100)
  UNIQUE CLUSTERED (c1) 
 ); 
  1. अद्वितीय क्लस्टर इंडेक्स के साथ तालिका बनाएं

  2. Temp "#Table" तालिका में डेटा डालें

  3. नॉन क्लस्टर्ड इंडेक्स बनाएं।

     CREATE NONCLUSTERED INDEX IX1  ON #Table (C2,C3);

अनावश्यक छँटाई से बचने के लिए इन्सर्ट स्टेटमेंट के बाद इंडेक्स बनाएं
Boopathi.Indotnet

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