क्या SQL सर्वर सिस्टम जनित बाधा नामों में टकराव पैदा कर सकता है?


14

मेरे पास एक एप्लिकेशन है जो SQL Server 2008 डेटाबेस (गैर क्लस्टर) में लाखों टेबल बनाता है। मैं SQL सर्वर 2014 (क्लस्टर) में अपग्रेड करना चाह रहा हूं, लेकिन लोड के दौरान एक त्रुटि संदेश मार रहा हूं:

"पहले से ही डेटाबेस में 'PK__tablenameprefix__179E2ED8F259C33B' नाम की एक वस्तु है"

यह एक सिस्टम जनित बाधा नाम है। यह एक बेतरतीब ढंग से उत्पन्न 64-बिट संख्या की तरह दिखता है। क्या यह संभव है कि मैं बड़ी संख्या में तालिकाओं के कारण टकराव देख रहा हूं? मान लें कि मेरे पास 100 मिलियन टेबल हैं, तो मैं अगले टेबल को जोड़ते समय टकराव की 1-इन -1 ट्रिलियन संभावना से कम की गणना करता हूं, लेकिन यह एक समान वितरण मानता है। क्या यह संभव है कि एसक्यूएल सर्वर ने टकराव की बाधाओं को बढ़ाने के लिए संस्करण 2008 और 2014 के बीच अपने नाम पीढ़ी के एल्गोरिथ्म को बदल दिया?

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

PS हाँ, मुझे पता है कि लाखों टेबल बनाना पागल है। यह ब्लैक बॉक्स 3rd पार्टी कोड है जिस पर मेरा कोई नियंत्रण नहीं है। पागलपन के बावजूद, इसने 2008 के संस्करण में काम किया और अब 2014 के संस्करण में नहीं है।

संपादित करें: करीब निरीक्षण पर, उत्पन्न प्रत्यय हमेशा 179E2ED8 के साथ शुरू होता है - जिसका अर्थ है कि यादृच्छिक भाग वास्तव में केवल एक 32-बिट संख्या है और टकराव की संभावना एक मात्र 1-50 है, हर बार एक नई तालिका जोड़ी जाती है, मैं देख रहा हूँ त्रुटि दर के लिए एक बहुत करीब मैच है!


तालिका के नाम अलग हैं, लेकिन वे एक नामकरण सम्मेलन का उपयोग करते हैं जिसके परिणामस्वरूप कम से कम पहले 11 अक्षर समान होते हैं, और ऐसा लगता है कि सभी SQL सर्वर का उपयोग बाधा नाम उत्पन्न करने में होता है।
jl6

अंतर्निहित हार्डवेयर अलग है (DL380 की नई पीढ़ी) लेकिन काफी उच्च प्रदर्शन नहीं है। अभ्यास का उद्देश्य एसक्यूएल सर्वर 2008 से बाहर की जगह लेना है, थ्रूपुट में सुधार नहीं करना है, और हार्डवेयर को इसके अनुसार प्रावधान किया गया है।
jl6

जवाबों:


16

क्या SQL सर्वर सिस्टम जनित बाधा नामों में टकराव पैदा कर सकता है?

यह SQL सर्वर की बाधा और संस्करण के प्रकार पर निर्भर करता है।

CREATE TABLE T1
(
A INT PRIMARY KEY CHECK (A > 0),
B INT DEFAULT -1 REFERENCES T1,
C INT UNIQUE,
CHECK (C > A)
)

SELECT name, 
       object_id, 
       CAST(object_id AS binary(4)) as object_id_hex,
       CAST(CASE WHEN object_id >= 16000057  THEN object_id -16000057 ELSE object_id +2131483591 END AS BINARY(4)) AS object_id_offset_hex
FROM sys.objects
WHERE parent_object_id = OBJECT_ID('T1')
ORDER BY name;

drop table T1

उदाहरण परिणाम 2008

+--------------------------+-----------+---------------+----------------------+
|           name           | object_id | object_id_hex | object_id_offset_hex |
+--------------------------+-----------+---------------+----------------------+
| CK__T1__1D498357         | 491357015 | 0x1D498357    | 0x1C555F1E           |
| CK__T1__A__1A6D16AC      | 443356844 | 0x1A6D16AC    | 0x1978F273           |
| DF__T1__B__1B613AE5      | 459356901 | 0x1B613AE5    | 0x1A6D16AC           |
| FK__T1__B__1C555F1E      | 475356958 | 0x1C555F1E    | 0x1B613AE5           |
| PK__T1__3BD019AE15A8618F | 379356616 | 0x169C85C8    | 0x15A8618F           |
| UQ__T1__3BD019A91884CE3A | 427356787 | 0x1978F273    | 0x1884CE3A           |
+--------------------------+-----------+---------------+----------------------+

उदाहरण परिणाम 2017

+--------------------------+------------+---------------+----------------------+
|           name           | object_id  | object_id_hex | object_id_offset_hex |
+--------------------------+------------+---------------+----------------------+
| CK__T1__59FA5E80         | 1509580416 | 0x59FA5E80    | 0x59063A47           |
| CK__T1__A__571DF1D5      | 1461580245 | 0x571DF1D5    | 0x5629CD9C           |
| DF__T1__B__5812160E      | 1477580302 | 0x5812160E    | 0x571DF1D5           |
| FK__T1__B__59063A47      | 1493580359 | 0x59063A47    | 0x5812160E           |
| PK__T1__3BD019AE0A4A6932 | 1429580131 | 0x5535A963    | 0x5441852A           |
| UQ__T1__3BD019A981F522E0 | 1445580188 | 0x5629CD9C    | 0x5535A963           |
+--------------------------+------------+---------------+----------------------+

डिफ़ॉल्ट बाधाओं के लिए, चेक की कमी और विदेशी कुंजी बाधा उत्पन्न ऑटो के अंतिम 4 बाइट्स बाधा के ऑब्जेक्ट के हेक्साडेसिमल संस्करण हैं। जैसा कि objectidअद्वितीय की गारंटी है नाम भी अद्वितीय होना चाहिए। Sybase में भी ये उपयोग करते हैंtabname_colname_objectid

अद्वितीय बाधाओं और प्राथमिक प्रमुख बाधाओं के लिए Sybase का उपयोग करता है

tabname_colname_tabindid, जहाँ tabindid तालिका ID और अनुक्रमणिका ID का एक स्ट्रिंग संयोजन है

यह भी विशिष्टता की गारंटी होगी।

SQL सर्वर इस योजना का उपयोग नहीं करता है।

SQL Server 2008 और 2017 दोनों में यह सिस्टम जनरेट किए गए नाम के अंत में एक 8 बाइट स्ट्रिंग का उपयोग करता है, हालांकि एल्गोरिथ्म में परिवर्तन किया गया है कि अंतिम 4 बाइट्स कैसे उत्पन्न होते हैं।

2008 में पिछले 4 बाइट्स एक हस्ताक्षरित पूर्णांक प्रचार करता है जो से ऑफसेट है प्रतिनिधित्व object_idद्वारा -16000057अधिकतम पर हस्ताक्षर किए पूर्णांक के आसपास किसी भी नकारात्मक मूल्य रैपिंग के साथ। (महत्व 16000057यह है कि यह क्रमिक रूप से बनाए गए के बीच लागू किया गया वेतन वृद्धि हैobject_id )। यह अभी भी विशिष्टता की गारंटी देता है।

2012 में ऊपर की ओर मुझे किसी भी पैटर्न पर बाधा के ऑब्जेक्ट_आईडी और नाम के अंतिम 8 वर्णों पर हस्ताक्षर करके प्राप्त किए गए पूर्णांक के रूप में हस्ताक्षरित इंट के हेक्साडेसिमल प्रतिनिधित्व के रूप में नहीं दिखता है।

2017 में कॉल स्टैक में फ़ंक्शन नामों से पता चलता है कि यह अब नाम पीढ़ी की प्रक्रिया के हिस्से के रूप में एक GUID बनाता है (2008 में मुझे कोई उल्लेख नहीं दिखता है MDConstraintNameGenerator)। मुझे लगता है कि यह यादृच्छिकता के कुछ स्रोत प्रदान करना है। स्पष्ट रूप से यह 4 बाइट्स में GUID से पूरे 16 बाइट्स का उपयोग नहीं कर रहा है जो कि बाधाओं के बीच बदलता है।

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

मुझे लगता है कि नए एल्गोरिथ्म को कुछ मामलों में दक्षता की वजह से किया गया था, जो आपके जैसे चरम मामलों में टकराव की कुछ बढ़ी हुई संभावना की कीमत पर किया गया था।

यह काफी पैथोलॉजिकल केस है क्योंकि इसमें पीके के टेबल नेम प्रीफिक्स और कॉलम के नाम की आवश्यकता होती है (इनोफ़र जैसा कि यह अंतिम 8 से पहले के 8 अक्षरों को प्रभावित करता है) दसियों हज़ारों टेबलों के समान होने से पहले यह संभावित हो जाता है लेकिन काफी पुन: पेश किया जा सकता है आसानी से नीचे के साथ।

CREATE OR ALTER PROC #P
AS
    SET NOCOUNT ON;

    DECLARE @I INT = 0;


    WHILE 1 = 1
      BEGIN
          EXEC ('CREATE TABLE abcdefghijklmnopqrstuvwxyz' + @I + '(C INT PRIMARY KEY)');
          SET @I +=1;
      END 

GO

EXEC #P

SQL सर्वर 2017 पर नव निर्मित डेटाबेस के विरुद्ध एक उदाहरण केवल एक मिनट में विफल हो गया (50,931 टेबल बनाए जाने के बाद)

Msg 2714, Level 16, State 30, Line 15 डेटाबेस में पहले से ही 'PK__abcdefgh__3BD019A8175067CE' नाम की एक वस्तु है। Msg 1750, Level 16, State 1, Line 15 बाधा या इंडेक्स नहीं बना सकता है। पिछली त्रुटियों को देखें।


11

मान लें कि मेरे पास 100 मिलियन टेबल हैं, तो मैं टकराव की 1-इन-1-ट्रिलियन संभावना से कम की गणना करता हूं

याद रखें यह " जन्मदिन की समस्या " है। आप किसी दिए गए हैश के लिए टकराव उत्पन्न करने की कोशिश नहीं कर रहे हैं, बल्कि इस संभावना को मापते हैं कि कई जोड़ी मूल्यों में से कोई भी टकराएगा नहीं।

तो एन टेबल के साथ, एन * (एन -1) / 2 जोड़े हैं, इसलिए यहां लगभग 10 16 जोड़े हैं। यदि टकराव की संभावना 2 -64 है , तो एकल जोड़ी के टकराने की संभावना 1-2 -64 नहीं है , लेकिन इतने सारे जोड़ों के साथ, यहां कोई टक्कर नहीं होने की संभावना लगभग (1-2 -64 ) 10 16 है , या 1 / 10,000 से अधिक। उदाहरण देखें https://preshing.com/20110504/hash-collision-probabilities/

और अगर यह केवल एक 32 बिट हैश टकराव की संभावना 1/2 पार केवल 77k मूल्यों पर है।


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