इस लेख में मैं समय . के संग्रहण आकार को देखता हूं SQL सर्वर में डेटा प्रकार।
विशेष रूप से, मैं निम्नलिखित को देखता हूं:
- Microsoft के दस्तावेज़
- एक चर में संग्रहीत डेटा
- बाइट्स में लंबाई
DATALENGTH()
का उपयोग कर रही है - बाइट्स में लंबाई
DATALENGTH()
का उपयोग कर रही है varbinary . में बदलने के बाद
- बाइट्स में लंबाई
- डेटाबेस में संग्रहीत डेटा
- बाइट्स में लंबाई
COL_LENGTH()
का उपयोग कर रही है - बाइट्स में लंबाई
DBCC PAGE()
का उपयोग कर रही है
- बाइट्स में लंबाई
Microsoft का दस्तावेज़ीकरण
समय . पर Microsoft का आधिकारिक दस्तावेज़ीकरण डेटा प्रकार इंगित करता है कि उपयोग की जा रही सटीकता के आधार पर इसका भंडारण आकार 3 और 5 बाइट्स के बीच है।
यह डेटा प्रकार उपयोगकर्ता द्वारा परिभाषित सटीकता की अनुमति देता है। आप समय(n) . का उपयोग कर सकते हैं सटीकता निर्दिष्ट करने के लिए, जहां n 0 और 7 के बीच का पैमाना है।
यहाँ वह डेटा है जो Microsoft समय के लिए प्रस्तुत करता है डेटा प्रकार:
निर्दिष्ट पैमाना | परिणाम (सटीक, पैमाना) | स्तंभ की लंबाई (बाइट्स) | आंशिक सेकंड की सटीकता |
---|---|---|---|
समय | (16,7) | 5 | 7 |
समय(0) | (8,0) | 3 | 0-2 |
समय(1) | (10,1) | 3 | 0-2 |
समय(2) | (11,2) | 3 | 0-2 |
समय(3) | (12,3) | 4 | 3-4 |
समय(4) | (13,4) | 4 | 3-4 |
समय(5) | (14,5) | 5 | 5-7 |
समय(6) | (15,6) | 5 | 5-7 |
समय(7) | (16,7) | 5 | 5-7 |
इस लेख के प्रयोजनों के लिए, मुझे मुख्य रूप से स्तंभ लंबाई (बाइट्स) . में दिलचस्पी है कॉलम। यह हमें बताता है कि इस डेटा प्रकार को डेटाबेस में संग्रहीत करने के लिए कितने बाइट्स का उपयोग किया जाता है।
उपयोगकर्ता के दृष्टिकोण से, समय डेटा प्रकार उसी तरह काम करता है जैसे datetime2 . का समय भाग . इसमें उपयोगकर्ता द्वारा परिभाषित भिन्नात्मक सेकंड की सटीकता है, और यह 0 से 7 के पैमाने को स्वीकार करता है।
इस लेख का शेष भाग विभिन्न उदाहरणों से चलता है जहां मैं समय . का संग्रहण आकार लौटाता हूं विभिन्न संदर्भों में मूल्य।
एक चर में संग्रहीत डेटा
सबसे पहले, मैं एक समय संग्रहित करूंगा/करूंगी एक चर में मान और उसके भंडारण आकार की जाँच करें। फिर मैं उस मान को varbinary . में बदल दूंगा और इसे दोबारा जांचें।
DATALENGTH का उपयोग करके बाइट्स में लंबाई
यदि हम DATALENGTH()
. का उपयोग करते हैं तो यहां क्या होता है समय(7) . के लिए उपयोग किए गए बाइट्स की संख्या वापस करने के लिए कार्य करता है मूल्य:
DECLARE @t time(7); SET @t = '10:15:30.1234567'; SELECT @t AS 'Value', DATALENGTH(@t) AS 'Length in Bytes';
परिणाम
+------------------+-------------------+ | Value | Length in Bytes | |------------------+-------------------| | 10:15:30.1234567 | 5 | +------------------+-------------------+
इस उदाहरण में मान का अधिकतम पैमाना 7 है (क्योंकि मैं वैरिएबल को time(7) . के रूप में घोषित करता हूं ), और यह 5 बाइट्स की लंबाई लौटाता है।
यह अपेक्षित है, क्योंकि यह Microsoft की तालिका में उल्लिखित संग्रहण आकार से मेल खाता है।
हालांकि, अगर हम मान को varbinary . में बदलते हैं हमें एक अलग परिणाम मिलता है।
'varbinary' में बदलने के बाद बाइट्स में लंबाई
कुछ डेवलपर समय में कनवर्ट करना पसंद करते हैं या डेटाटाइम2 varbinary . के चर क्योंकि यह इस बात का अधिक प्रतिनिधि है कि SQL सर्वर इसे डेटाबेस में कैसे संग्रहीत करता है। हालांकि यह आंशिक रूप से सच है, परिणाम बिल्कुल संग्रहीत मूल्य के समान नहीं हैं (उस पर अधिक नीचे)।
अगर हम अपना समय . बदलते हैं तो यहां क्या होता है varbinary . का मान :
DECLARE @t time(7); SET @t = '10:15:30.1234567'; SELECT CONVERT(VARBINARY(16), @t) AS 'Value', DATALENGTH(CONVERT(VARBINARY(16), @t)) AS 'Length in Bytes';
परिणाम
+----------------+-------------------+ | Value | Length in Bytes | |----------------+-------------------| | 0x0787A311FC55 | 6 | +----------------+-------------------+
इस मामले में हमें 6 बाइट्स मिलते हैं। हमारा मूल्य अब दस्तावेज़ में बताए गए से 1 अधिक बाइट का उपयोग करता है।
ऐसा इसलिए है क्योंकि इसे सटीक स्टोर करने के लिए अतिरिक्त बाइट की आवश्यकता होती है।
यह समय . का हेक्साडेसिमल निरूपण है मूल्य। वास्तविक समय मान (और इसकी सटीकता) 0x
. के बाद सब कुछ है . हेक्स वर्णों की प्रत्येक जोड़ी एक बाइट है। 6 जोड़े हैं, और इसलिए 6 बाइट्स हैं। इसकी पुष्टि तब होती है जब हम DATALENGTH()
. का उपयोग करते हैं लंबाई को बाइट्स में वापस करने के लिए।
इस उदाहरण में हम देख सकते हैं कि पहली बाइट 07
. है . यह सटीकता का प्रतिनिधित्व करता है (मैंने 7 के पैमाने का उपयोग किया है और इसलिए यहां प्रदर्शित किया गया है)।
अगर मैं स्केल बदलता हूं, तो हम देख सकते हैं कि स्केल से मेल खाने के लिए पहला बाइट बदलता है:
DECLARE @t time(3); SET @t = '10:15:30.1234567'; SELECT CONVERT(VARBINARY(16), @t) AS 'Value', DATALENGTH(CONVERT(VARBINARY(16), @t)) AS 'Length in Bytes';
परिणाम
+--------------+-------------------+ | Value | Length in Bytes | |--------------+-------------------| | 0x034B823302 | 5 | +--------------+-------------------+
हम यह भी देख सकते हैं कि लंबाई तदनुसार कम हो गई है। लेकिन फिर से, यह दस्तावेज़ीकरण के अनुसार उपयोग किए जाने वाले से एक और बाइट है।
हालांकि Microsoft के दस्तावेज़ समय . के लिए इसका स्पष्ट उल्लेख नहीं है, datetime2 . के लिए दस्तावेज़ीकरण निम्नलिखित बताता है:
<ब्लॉकक्वॉट>datetime2 . का पहला बाइट value मूल्य की शुद्धता को संग्रहीत करता है, जिसका अर्थ है कि datetime2 . के लिए आवश्यक वास्तविक संग्रहण value ऊपर दी गई तालिका में दर्शाया गया संग्रहण आकार है और सटीकता को संग्रहीत करने के लिए 1 अतिरिक्त बाइट है। यह एक datetime2 . का अधिकतम आकार बनाता है मान 9 बाइट्स – 1 बाइट सटीक रूप से संग्रहीत करता है और डेटा संग्रहण के लिए अधिकतम सटीकता पर 8 बाइट्स।
और डेटाटाइम2 उपरोक्त उदाहरणों के संबंध में डेटा प्रकार ठीक उसी तरह काम करता है। दूसरे शब्दों में, यह केवल अतिरिक्त बाइट की रिपोर्ट करता है जब इसे varbinary . में परिवर्तित किया जाता है ।
तो Microsoft दस्तावेज़ में उल्लिखित अतिरिक्त बाइट भी समय . पर लागू होता प्रतीत होता है ।
हालांकि, आपके समय . का वास्तविक संग्रहण आकार मान उस स्थान पर होंगे जहां डेटा संग्रहीत किया जाता है।
डेटाबेस में संग्रहीत डेटा
जब डेटाबेस कॉलम में एक प्रकार का समय . होता है , इसकी सटीकता स्तंभ स्तर पर निर्दिष्ट है - नहीं डेटा स्तर पर। दूसरे शब्दों में, यह पूरे कॉलम के लिए एक बार निर्दिष्ट किया जाता है। यह समझ में आता है, क्योंकि जब आप किसी कॉलम को time(7) . के रूप में परिभाषित करते हैं , आप जानते हैं कि सभी पंक्तियां समय(7) . होंगी . प्रत्येक पंक्ति पर उस तथ्य को पुन:स्थापित करते हुए कीमती बाइट्स का उपयोग करने की आवश्यकता नहीं है।
जब आप समय . की जांच करते हैं मान के रूप में यह SQL सर्वर में संग्रहीत है, तो आप देखेंगे कि यह varbinary जैसा ही है परिणाम, लेकिन बिना सटीकता।
नीचे ऐसे उदाहरण दिए गए हैं जो दिखाते हैं कि कैसे समय मान SQL सर्वर में संग्रहीत हैं।
इन उदाहरणों में, मैं विभिन्न समय(n) . के साथ एक डेटाबेस बनाता हूं कॉलम, और फिर COL_LENGTH()
. का उपयोग करें प्रत्येक कॉलम की लंबाई, बाइट्स में वापस करने के लिए। फिर मैं DBCC PAGE
. का उपयोग करने से पहले उन स्तंभों में मान सम्मिलित करता हूं प्रत्येक समय . के संग्रहण आकार की जांच करने के लिए पृष्ठ फ़ाइल पर मान लेता है।
एक डेटाबेस बनाएं:
CREATE DATABASE Test;
एक टेबल बनाएं:
USE Test; CREATE TABLE TimeTest ( t0 time(0), t1 time(1), t2 time(2), t3 time(3), t4 time(4), t5 time(5), t6 time(6), t7 time(7) );
इस मामले में मैं आठ कॉलम बनाता हूं - प्रत्येक उपयोगकर्ता परिभाषित पैमाने के लिए एक जिसे हम time(n) के साथ उपयोग कर सकते हैं ।
अब हम प्रत्येक कॉलम के स्टोरेज साइज की जांच कर सकते हैं।
COL_LENGTH() का उपयोग करके बाइट्स में लंबाई
COL_LENGTH()
का उपयोग करें प्रत्येक कॉलम की लंबाई (बाइट्स में) जांचने के लिए:
SELECT COL_LENGTH ( 'TimeTest' , 't0' ) AS 't0', COL_LENGTH ( 'TimeTest' , 't1' ) AS 't1', COL_LENGTH ( 'TimeTest' , 't2' ) AS 't2', COL_LENGTH ( 'TimeTest' , 't3' ) AS 't3', COL_LENGTH ( 'TimeTest' , 't4' ) AS 't4', COL_LENGTH ( 'TimeTest' , 't5' ) AS 't5', COL_LENGTH ( 'TimeTest' , 't6' ) AS 't6', COL_LENGTH ( 'TimeTest' , 't7' ) AS 't7';
परिणाम:
+------+------+------+------+------+------+------+------+ | t0 | t1 | t2 | t3 | t4 | t5 | t6 | t7 | |------+------+------+------+------+------+------+------| | 3 | 3 | 3 | 4 | 4 | 5 | 5 | 5 | +------+------+------+------+------+------+------+------+
तो एक बार फिर, हमें वही परिणाम मिलता है जो दस्तावेज़ीकरण बताता है कि हमें मिलेगा। इसकी उम्मीद की जानी चाहिए, क्योंकि दस्तावेज़ीकरण स्पष्ट रूप से "कॉलम की लंबाई (बाइट्स)" बताता है, जिसे हम यहां माप रहे हैं।
याद रखें, यह पहले . है हम कोई डेटा डालते हैं। कॉलम स्वयं डाले गए किसी भी डेटा की सटीकता (और इसलिए भंडारण आकार) निर्धारित करते हैं - दूसरी तरफ नहीं।
संग्रहीत डेटा की जांच के लिए DBCC पृष्ठ का उपयोग करें
अब डेटा डालें, फिर DBCC PAGE
का उपयोग करें डेटा का वास्तविक संग्रहण आकार खोजने के लिए जिसे हम प्रत्येक कॉलम में संग्रहीत करते हैं।
डेटा डालें:
DECLARE @t time(7) = '10:15:30.1234567'; INSERT INTO TimeTest ( t0, t1, t2, t3, t4, t5, t6, t7 ) SELECT @t, @t, @t, @t, @t, @t, @t, @t;
अब डेटा चुनें (बस इसे जांचने के लिए):
SELECT * FROM TimeTest;
परिणाम (ऊर्ध्वाधर आउटपुट का उपयोग करके):
t0 | 10:15:30 t1 | 10:15:30.1000000 t2 | 10:15:30.1200000 t3 | 10:15:30.1230000 t4 | 10:15:30.1235000 t5 | 10:15:30.1234600 t6 | 10:15:30.1234570 t7 | 10:15:30.1234567
जैसा कि अपेक्षित था, मान उस सटीकता का उपयोग करते हैं जो पहले स्तंभ स्तर पर निर्दिष्ट की गई थी।
ध्यान दें कि मेरा सिस्टम अनुगामी शून्य प्रदर्शित करता है। आपका ऐसा हो भी सकता है और नहीं भी। भले ही, यह वास्तविक सटीकता या सटीकता को प्रभावित नहीं करता है।
अब, इससे पहले कि हम DBCC PAGE()
का उपयोग करें , हमें यह जानने की जरूरत है कि इसे कौन सा पेजपीआईडी पास करना है। हम उपयोग कर सकते हैं DBCC IND()
उसे खोजने के लिए।
पेजपीआईडी ढूंढें:
DBCC IND('Test', 'dbo.TimeTest', 0);
परिणाम (ऊर्ध्वाधर आउटपुट का उपयोग करके):
-[ RECORD 1 ]------------------------- PageFID | 1 PagePID | 308 IAMFID | NULL IAMPID | NULL ObjectID | 1541580530 IndexID | 0 PartitionNumber | 1 PartitionID | 72057594043236352 iam_chain_type | In-row data PageType | 10 IndexLevel | NULL NextPageFID | 0 NextPagePID | 0 PrevPageFID | 0 PrevPagePID | 0 -[ RECORD 2 ]------------------------- PageFID | 1 PagePID | 384 IAMFID | 1 IAMPID | 308 ObjectID | 1541580530 IndexID | 0 PartitionNumber | 1 PartitionID | 72057594043236352 iam_chain_type | In-row data PageType | 1 IndexLevel | 0 NextPageFID | 0 NextPagePID | 0 PrevPageFID | 0 PrevPagePID | 0
यह दो रिकॉर्ड देता है। हम 1 के पेज टाइप (दूसरा रिकॉर्ड) में रुचि रखते हैं। हम उस रिकॉर्ड से PagePID चाहते हैं। इस मामले में पेजपीआईडी 384 . है ।
अब हम उस पेजपीआईडी को ले सकते हैं और इसे निम्नलिखित में उपयोग कर सकते हैं:
DBCC TRACEON(3604, -1); DBCC PAGE(Test, 1, 384, 3);
अभी हम मुख्य रूप से निम्नलिखित भाग में रुचि रखते हैं:
Slot 0 Column 1 Offset 0x4 Length 3 Length (physical) 3 t0 = 10:15:30 Slot 0 Column 2 Offset 0x7 Length 3 Length (physical) 3 t1 = 10:15:30.1 Slot 0 Column 3 Offset 0xa Length 3 Length (physical) 3 t2 = 10:15:30.12 Slot 0 Column 4 Offset 0xd Length 4 Length (physical) 4 t3 = 10:15:30.123 Slot 0 Column 5 Offset 0x11 Length 4 Length (physical) 4 t4 = 10:15:30.1235 Slot 0 Column 6 Offset 0x15 Length 5 Length (physical) 5 t5 = 10:15:30.12346 Slot 0 Column 7 Offset 0x1a Length 5 Length (physical) 5 t6 = 10:15:30.123457 Slot 0 Column 8 Offset 0x1f Length 5 Length (physical) 5 t7 = 10:15:30.1234567
इसलिए हमें वही परिणाम मिलता है जो दस्तावेज़ीकरण कहता है। यह सुझाव देगा कि सटीकता को मानों के साथ संग्रहीत नहीं किया जा रहा है।
हम वास्तविक डेटा की जांच करके इसकी पुष्टि कर सकते हैं।
वास्तविक समय मान पृष्ठ फ़ाइल के इस भाग में संग्रहीत होते हैं:
Memory Dump @0x0000000423ADA060 0000000000000000: 10002400 42900095 a205d459 384b8233 02f31603 ..$.B..¢.ÔY8K3.ó.. 0000000000000014: 167ae51e dc00c1f6 34990887 a311fc55 080000 .zå.Ü.Áö4..£.üU...
हम कुछ चीजों को हटाकर वास्तविक समय मान निकाल सकते हैं। एक बार हटा दिए जाने के बाद, निम्नलिखित रहेंगे:
42900095 a205d459 384b8233 02f31603 167ae51e dc00c1f6 34990887 a311fc55
इन हेक्स अंकों में हमारा सारा समय डेटा होता है, लेकिन सटीकता नहीं . हालांकि, उन्हें 4 बाइट विखंडू में व्यवस्थित किया गया है, इसलिए हमें अलग-अलग मान प्राप्त करने के लिए रिक्त स्थान को पुनर्व्यवस्थित करना होगा।
यहाँ अंतिम परिणाम है। मैंने बेहतर पठनीयता के लिए प्रत्येक दिनांक/समय मान को एक नई पंक्ति पर रखा है।
429000 95a205 d45938 4b823302 f3160316 7ae51edc00 c1f6349908 87a311fc55
वे वास्तविक हेक्साडेसिमल मान हैं (सटीक घटाकर ) अगर हम समय . को परिवर्तित करते हैं तो हमें मिलेगा varbinary . का मान . इस तरह:
SELECT CONVERT(VARBINARY(16), t0) AS 't0', CONVERT(VARBINARY(16), t1) AS 't1', CONVERT(VARBINARY(16), t2) AS 't2', CONVERT(VARBINARY(16), t3) AS 't3', CONVERT(VARBINARY(16), t4) AS 't4', CONVERT(VARBINARY(16), t5) AS 't5', CONVERT(VARBINARY(16), t6) AS 't6', CONVERT(VARBINARY(16), t7) AS 't7' FROM TimeTest;
परिणाम (ऊर्ध्वाधर आउटपुट का उपयोग करके):
t0 | 0x00429000 t1 | 0x0195A205 t2 | 0x02D45938 t3 | 0x034B823302 t4 | 0x04F3160316 t5 | 0x057AE51EDC00 t6 | 0x06C1F6349908 t7 | 0x0787A311FC55
वह क्वेरी एक ही परिणाम उत्पन्न करती है - सिवाय इसके कि प्रत्येक मान को सटीकता के साथ जोड़ा गया है।
यहां एक तालिका है जो वास्तविक पृष्ठ फ़ाइल डेटा की तुलना CONVERT()
के परिणामों से करती है ऑपरेशन।
पृष्ठ फ़ाइल डेटा | कन्वर्ट () डेटा |
---|---|
429000 | 00429000 |
95a205 | 0195A205 |
d45938 | 02D45938 |
4b823302 | 034B823302 |
f3160316 | 04F3160316 |
7ae51edc00 | 057AE51EDC00 |
c1f6349908 | 06C1F6349908 |
87a311fc55 | 0787A311FC55 |
इसलिए हम देख सकते हैं कि पृष्ठ फ़ाइल सटीकता को संग्रहीत नहीं करती है, लेकिन परिवर्तित परिणाम करता है।
मैंने वास्तविक दिनांक और समय भागों को लाल रंग में हाइलाइट किया। मैंने 0x
. भी हटा दिया है परिवर्तित परिणामों से उपसर्ग, ताकि केवल वास्तविक दिनांक/समय डेटा प्रदर्शित हो (सटीकता के साथ)।
यह भी ध्यान दें कि हेक्साडेसिमल केस-असंवेदनशील है, इसलिए यह तथ्य कि एक लोअरकेस का उपयोग करता है और दूसरा अपरकेस का उपयोग करता है, कोई समस्या नहीं है।
निष्कर्ष
समय . परिवर्तित करते समय varbinary . का मान , इसे सटीक स्टोर करने के लिए एक अतिरिक्त बाइट की आवश्यकता होती है। समय के हिस्से की व्याख्या करने के लिए इसे सटीकता की आवश्यकता होती है (क्योंकि यह एक समय अंतराल के रूप में संग्रहीत होता है, जिसका सटीक मूल्य सटीकता पर निर्भर करेगा)।
जब एक डेटाबेस में संग्रहीत किया जाता है, तो कॉलम स्तर पर एक बार सटीकता निर्दिष्ट की जाती है। यह तार्किक लगता है, क्योंकि प्रत्येक पंक्ति में सटीकता जोड़ने की कोई आवश्यकता नहीं है जब सभी पंक्तियों में वैसे भी समान सटीकता हो। इसके लिए प्रत्येक पंक्ति के लिए एक अतिरिक्त बाइट की आवश्यकता होगी, जो अनावश्यक रूप से भंडारण आवश्यकताओं को बढ़ाएगी।