Database
 sql >> डेटाबेस >  >> RDS >> Database

पहचान कॉलम को चौड़ा करने के प्रभाव को कम करना - भाग 2

[ भाग 1 | भाग 2 | भाग 3 | भाग 4 ]

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

प्राथमिक कुंजी

उम्मीद है कि आपकी सभी तालिकाओं में प्राथमिक कुंजी होगी; यदि पहचान कॉलम शामिल है, हालांकि, अंतर्निहित डेटा प्रकार को बदलना इतना आसान नहीं होगा। ये सरल उदाहरण लें, संकुल और गैर-संकुल प्राथमिक कुंजियाँ दोनों:

CREATE TABLE dbo.Test1
(
  ID INT IDENTITY(1,1),
  CONSTRAINT PK_1 PRIMARY KEY NONCLUSTERED (ID)
);
 
CREATE TABLE dbo.Test2
(
  ID INT IDENTITY(1,1),
  CONSTRAINT PK_2 PRIMARY KEY CLUSTERED (ID)
);

अगर मैं कॉलम बदलने की कोशिश करता हूं:

ALTER TABLE dbo.Test1 ALTER COLUMN ID BIGINT;
GO
ALTER TABLE dbo.Test2 ALTER COLUMN ID BIGINT;

मुझे प्रत्येक ALTER के लिए त्रुटि संदेशों की एक जोड़ी मिलती है (केवल पहली जोड़ी दिखा रहा है):

Msg 5074, Level 16, State 1
ऑब्जेक्ट 'PK_1' कॉलम 'ID' पर निर्भर है।
Msg 4922, Level 16, State 9
ALTER TABLE ALTER COLUMN ID विफल हो गया क्योंकि एक या अधिक ऑब्जेक्ट इस कॉलम तक पहुँचते हैं।

सारांश:हमें प्राथमिक कुंजी छोड़नी होगी , क्लस्टर किया गया है या नहीं।

सूचकांक

आइए पहले ऊपर की तरह कुछ टेबल लेते हैं, और प्राथमिक कुंजी के बजाय एक अद्वितीय अनुक्रमणिका का उपयोग करते हैं:

CREATE TABLE dbo.Test3
(
  ID INT IDENTITY(1,1),
  INDEX IX_3 UNIQUE NONCLUSTERED (ID)
);
 
CREATE TABLE dbo.Test4
(
  ID INT IDENTITY(1,1),
  INDEX IX_4 UNIQUE CLUSTERED (ID) 
);

ऊपर समान ALTER आदेश चलाने से, वही त्रुटि संदेश प्राप्त होते हैं। यह सही रहता है भले ही मैं अनुक्रमणिका अक्षम कर दूं:

ALTER INDEX IX_3 ON dbo.Test3 DISABLE;
GO
ALTER INDEX IX_4 ON dbo.Test4 DISABLE;

विभिन्न अन्य प्रकार के इंडेक्स संयोजनों के लिए समान परिणाम, जैसे कि एक सम्मिलित कॉलम या एक फ़िल्टर:

CREATE TABLE dbo.Test5
(
  ID INT IDENTITY(1,1),
  x CHAR(1)
);
CREATE INDEX IX_5 ON dbo.Test5(x) INCLUDE(ID);
 
CREATE TABLE dbo.Test6
(
  ID INT IDENTITY(1,1),
  x CHAR(1)
);
CREATE INDEX IX_6 ON dbo.Test6(x) WHERE ID > 0;

सारांश:हमें किसी भी अनुक्रमणिका को छोड़ना और फिर से बनाना होगा , क्लस्टर या नहीं, जो पहचान कॉलम को संदर्भित करता है - कुंजी या INCLUDE में। यदि IDENTITY स्तंभ संकुल अनुक्रमणिका का भाग है, तो इसका अर्थ है सभी अनुक्रमणिका , क्योंकि वे सभी परिभाषा के अनुसार क्लस्टरिंग कुंजी का संदर्भ देंगे। और उन्हें अक्षम करना पर्याप्त नहीं है।

गणना किए गए कॉलम

हालांकि यह अपेक्षाकृत दुर्लभ होना चाहिए, मैंने पहचान कॉलम के आधार पर गणना किए गए कॉलम देखे हैं। उदाहरण के लिए:

CREATE TABLE dbo.Test7
(
  ID INT IDENTITY(1,1),
  NextID AS (ID + 1)
);

इस बार, जब हम बदलने की कोशिश करते हैं, तो हमें वही त्रुटियां मिलती हैं, लेकिन थोड़े अलग टेक्स्ट के साथ:

Msg 5074, Level 16, State 1
कॉलम 'NextID' कॉलम 'ID' पर निर्भर है।
Msg 4922, Level 16, State 9
ALTER TABLE ALTER COLUMN ID विफल हो गया क्योंकि एक या अधिक ऑब्जेक्ट इस कॉलम तक पहुँचते हैं।

यह तब भी सही है जब हम लक्ष्य डेटा प्रकार से मेल खाने के लिए परिकलित स्तंभ परिभाषा को बदलते हैं:

CREATE TABLE dbo.Test8
(
  ID INT IDENTITY(1,1),
  NextID AS (CONVERT(BIGINT, ID) + 1)
);

सारांश:हमें परिकलित स्तंभों की परिभाषा बदलनी होगी, या उन्हें पूरी तरह से छोड़ना होगा।

अनुक्रमित दृश्य

अनुक्रमित विचार उनके उपयोग के उचित हिस्से को भी देखते हैं। आइए एक अनुक्रमित दृश्य का निर्माण करें जो पहचान कॉलम का संदर्भ भी नहीं देता (ध्यान दें कि कोई अन्य अनुक्रमणिका या आधार तालिका पर बाधाएं नहीं हैं):

CREATE TABLE dbo.Test9
(
  ID INT IDENTITY(1,1),
  x CHAR(1)
);
GO
 
CREATE VIEW dbo.vTest9A
WITH SCHEMABINDING
AS
  SELECT x, c = COUNT_BIG(*)
    FROM dbo.Test9
    GROUP BY x;
GO
 
CREATE UNIQUE CLUSTERED INDEX IX_9A ON dbo.vTest9A(x);

एक बार फिर, हम ALTER का प्रयास करेंगे, और इस बार यह सफल हुआ . मैं कबूल करूंगा कि मैं इससे हैरान था, क्योंकि SCHEMABINDING को अंतर्निहित तालिका में किसी भी बदलाव को रोकने के लिए माना जाता है, लेकिन इस मामले में यह केवल दृश्य में स्पष्ट रूप से संदर्भित कॉलम पर लागू होता है। अगर हम थोड़ा अलग दृश्य बनाते हैं:

CREATE VIEW dbo.vTest9B
WITH SCHEMABINDING
AS
  SELECT ID, c = COUNT_BIG(*)
    FROM dbo.Test9
    GROUP BY ID;
GO
CREATE UNIQUE CLUSTERED INDEX IX_9B ON dbo.vTest9B(ID);

अब हम स्तंभ निर्भरता के कारण विफल हो जाएंगे:

Msg 5074, Level 16, State 1
ऑब्जेक्ट 'vTest9B' कॉलम 'ID' पर निर्भर है।
Msg 4922, Level 16, State 9
ALTER TABLE ALTER COLUMN ID विफल हुआ क्योंकि एक या अधिक ऑब्जेक्ट इस कॉलम तक पहुँचते हैं।

सारांश:हमें ऐसे किसी भी दृश्य पर सभी अनुक्रमणिकाएँ छोड़नी होंगी जो स्पष्ट रूप से पहचान स्तंभ का संदर्भ देती हों , साथ ही सभी अनुक्रमणिका किसी भी दृश्य पर जो अपने क्लस्टर इंडेक्स में पहचान कॉलम का संदर्भ देता है।

इनबाउंड विदेशी कुंजियां

शायद पहचान प्राथमिक कुंजी का सबसे समस्याग्रस्त पहलू यह है कि सरोगेट की प्रकृति से पूरे बिंदु को अक्सर कई संबंधित तालिकाओं में इस सरोगेट कुंजी का उपयोग करना होता है। अब, मैं संदर्भात्मक अखंडता से बचने की वकालत करने वाला नहीं हूं, लेकिन यह संभावित रूप से यहां भी हमारे रास्ते में खड़ा होने वाला है। हम ऊपर से जानते हैं कि हम उस कॉलम को नहीं बदल सकते हैं जो प्राथमिक कुंजी या अद्वितीय बाधा का हिस्सा है, और किसी अन्य तालिका के लिए एक विदेशी कुंजी बाधा के साथ यहां इंगित करने के लिए, उन दो चीजों में से एक का अस्तित्व होना चाहिए। तो मान लें कि हमारे पास निम्नलिखित दो टेबल हैं:

CREATE TABLE dbo.TestParent
(
  ID INT IDENTITY(1,1),
  CONSTRAINT PK_Parent PRIMARY KEY CLUSTERED(ID)
);
GO
 
CREATE TABLE dbo.TestChild
(
  ParentID INT NOT NULL,
  CONSTRAINT FK_Parent FOREIGN KEY(ParentID) REFERENCES dbo.TestParent(ID)
);

इससे पहले कि हम कॉलम के डेटा प्रकार को बदलने पर भी विचार कर सकें, हमें बाधाओं को छोड़ना होगा:

ALTER TABLE dbo.TestParent DROP CONSTRAINT PK_Parent;

और निश्चित रूप से हम विदेशी कुंजी बाधा को छोड़े बिना नहीं कर सकते, क्योंकि इससे निम्न त्रुटि संदेश प्राप्त होता है:

संदेश 3725, स्तर 16, राज्य 0
बाधा 'PK_Parent' तालिका 'TestChild' द्वारा संदर्भित किया जा रहा है, विदेशी कुंजी बाधा 'FK_Parent'।
संदेश 3727, स्तर 16, राज्य 0
हो सकता है बाधा नहीं छोड़ें। पिछली त्रुटियां देखें।

यह त्रुटि तब भी बनी रहती है जब हम पहले विदेशी कुंजी बाधा को अक्षम करते हैं:

ALTER TABLE dbo.TestChild NOCHECK CONSTRAINT FK_Parent;

इसके ऊपर, विचार करें कि आपको उनके डेटा प्रकार को भी बदलने के लिए संदर्भ कॉलम की आवश्यकता होगी। और इसके अलावा, वे कॉलम संभवतः उपरोक्त कुछ तत्वों में भाग लेते हैं जो समान रूप से चाइल्ड टेबल पर परिवर्तन को रोक सकते हैं। चीजों को पूरी तरह से सहसंयोजक और समन्वयित करने के लिए, हमें यह करना होगा:

  • प्रासंगिक बाधाओं और अनुक्रमणिका को मूल तालिका पर छोड़ दें
  • चाइल्ड टेबल पर प्रासंगिक विदेशी कुंजी बाधाओं को छोड़ें
  • FK कॉलम को संदर्भित करने वाले चाइल्ड टेबल पर किसी भी इंडेक्स को ड्रॉप करें (और किसी भी प्रासंगिक कंप्यूटेड कॉलम / इंडेक्स किए गए दृश्यों से निपटें)
  • पैरेंट और सभी चाइल्ड टेबल पर डेटा प्रकार बदलें
  • सब कुछ फिर से बनाएं

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

निष्कर्ष

मुझे पता है कि ऐसा लगता है कि हम धीरे-धीरे आगे बढ़ रहे हैं, और मैं मानता हूं कि इस पोस्ट में मैं एक समाधान की बजाय एक समाधान से दूर जा रहा हूं। मैं वहां पहुंचूंगा, पहले प्रस्तुत करने के लिए बहुत सारी जानकारी है, जिसमें वे चीजें भी शामिल हैं जो इस प्रकार के परिवर्तन को कठिन बनाती हैं। उपरोक्त सारांशों से हटाकर, हमें निम्न करने की आवश्यकता होगी:

  • मुख्य तालिका पर प्रासंगिक अनुक्रमणिका छोड़ें और फिर से बनाएं
  • पहचान कॉलम वाले कंप्यूटेड कॉलम को बदलें या छोड़ें
  • अनुक्रमित दृश्यों पर अनुक्रमणिका छोड़ें जो IDENTITY स्तंभ का संदर्भ देती हैं
  • पहचान कॉलम को इंगित करने वाली इनबाउंड विदेशी कुंजियों से निपटें

दुर्भाग्य से, इनमें से बहुत सी चीजें कैच-22 हैं। आप एक कॉलम नहीं बदल सकते क्योंकि एक इंडेक्स उस पर निर्भर करता है, और आप इंडेक्स को तब तक नहीं बदल सकते जब तक कि कॉलम बदल न जाए। क्या यह बहुत अच्छा नहीं होगा यदि ALTER INDEX समर्थित REBUILD WITH (ONLINE = ON, CHANGE_COLUMN (COLUMN = ID, NEW_TYPE = BIGINT)) ? और CASCADE_CHANGE_TO_REFERENCING_KEYS,COLUMNS,INDEXES,VIEWS,ETC ? ठीक है, यह नहीं है (मैंने जाँच की)। इसलिए, हमें इन चीजों को आसान बनाने के तरीके खोजने की जरूरत है। कृपया भाग 3 के लिए बने रहें।

[ भाग 1 | भाग 2 | भाग 3 | भाग 4 ]


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Django 1.6 . के साथ लेनदेन प्रबंधन

  2. बच्चों की पार्टी डेटा मॉडल

  3. समस्या सेट 1 - संस्थाओं की पहचान

  4. अनुप्रयोगों के बीच डेटाबेस संरचना को सिंक्रनाइज़ करना

  5. DBCC CheckDB फ़ंक्शन का अवलोकन