PostgreSQL डेटाबेस में मुझे किस टाइमस्टैम्प प्रकार का चयन करना चाहिए?


119

मैं एक बहु-समयक्षेत्र परियोजना के संदर्भ में अपने पोस्टग्रेज डेटाबेस में टाइमस्टैम्प के भंडारण के लिए एक सर्वोत्तम अभ्यास को परिभाषित करना चाहूंगा।

हाँ मैं

  1. चुनें TIMESTAMP WITHOUT TIME ZONEऔर याद रखें कि इस क्षेत्र के लिए सम्मिलन समय में किस समय का उपयोग किया गया था
  2. TIMESTAMP WITHOUT TIME ZONEएक अन्य फ़ील्ड चुनें और जोड़ें जिसमें उस टाइमज़ोन का नाम होगा जो प्रविष्टि के समय उपयोग किया गया था
  3. TIMESTAMP WITH TIME ZONEतदनुसार टाइमस्टैम्प चुनें और डालें

मेरे पास विकल्प 3 के लिए थोड़ी वरीयता है (टाइम ज़ोन के साथ टाइमस्टैम्प) लेकिन मैं इस मामले पर एक शिक्षित राय रखना चाहूंगा।

जवाबों:


142

सबसे पहले, PostgreSQL का समय संभालना और अंकगणित शानदार है और विकल्प 3 सामान्य मामले में ठीक है। हालांकि, यह समय और टाइमज़ोन का एक अधूरा दृश्य है और इसे पूरक किया जा सकता है:

  1. उपयोगकर्ता वरीयता के रूप में उपयोगकर्ता के समय क्षेत्र का नाम संग्रहीत करें (उदाहरण के लिए America/Los_Angeles, नहीं -0700)।
  2. उपयोगकर्ता घटनाओं / समय डेटा को उनके संदर्भ के फ्रेम में स्थानीय प्रस्तुत किया है (सबसे अधिक संभावना यूटीसी से एक ऑफसेट, जैसे -0700)।
  3. आवेदन में, UTCएक TIMESTAMP WITH TIME ZONEकॉलम का उपयोग करके समय को संग्रहीत और संग्रहीत करें।
  4. वापसी समय एक उपयोगकर्ता के समय क्षेत्र (से यानी परिवर्तित करने के लिए स्थानीय अनुरोध करता है UTCकरने के लिए America/Los_Angeles)।
  5. अपने डेटाबेस है सेट timezoneकरने के लिए UTC

यह विकल्प हमेशा काम नहीं करता है क्योंकि उपयोगकर्ता के समय क्षेत्र को प्राप्त करना कठिन हो सकता है और इसलिए TIMESTAMP WITH TIME ZONEहल्के अनुप्रयोगों के लिए उपयोग करने की हेज सलाह । उस ने कहा, मुझे इस विकल्प 4 के कुछ पृष्ठभूमि पहलुओं के बारे में अधिक विस्तार से बताएं।

विकल्प 3 की तरह, इसका कारण यह WITH TIME ZONEहै कि जिस समय कुछ हुआ है वह समय में एक निरपेक्ष क्षण है। WITHOUT TIME ZONEएक सापेक्ष समय क्षेत्र देता है। कभी भी, कभी भी, कभी भी पूर्ण और सापेक्ष टाइमस्टैम्प्स का मिश्रण न करें।

एक प्रोग्रामेटिक और स्थिरता के दृष्टिकोण से, सुनिश्चित करें कि सभी गणना यूटीसी को समय क्षेत्र के रूप में उपयोग कर रहे हैं। यह एक PostgreSQL आवश्यकता नहीं है, लेकिन यह अन्य प्रोग्रामिंग भाषाओं या वातावरण के साथ एकीकरण करते समय मदद करता है। एक की स्थापना CHECKसुनिश्चित करें कि समय स्टाम्प स्तंभ के लिए लिखने बनाने के लिए स्तंभ पर एक समय क्षेत्र ऑफसेट है 0एक रक्षात्मक स्थिति है कि रोकता है कीड़े के कुछ वर्गों (जैसे एक स्क्रिप्ट एक फाइल करने के लिए डेटा उदासीनता और कुछ और एक का उपयोग कर समय डेटा सॉर्ट करता शाब्दिक प्रकार)। फिर से, PostgreSQL को तिथि गणना सही ढंग से करने या समय क्षेत्र के बीच परिवर्तित करने की आवश्यकता नहीं है (अर्थात PostgreSQL किसी भी दो मनमाने समय क्षेत्रों के बीच समय बदलने में बहुत माहिर है)। यह सुनिश्चित करने के लिए कि डेटाबेस में डेटा शून्य से भरा गया है:

CREATE TABLE my_tbl (
  my_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
  CHECK(EXTRACT(TIMEZONE FROM my_timestamp) = '0')
);
test=> SET timezone = 'America/Los_Angeles';
SET
test=> INSERT INTO my_tbl (my_timestamp) VALUES (NOW());
ERROR:  new row for relation "my_tbl" violates check constraint "my_tbl_my_timestamp_check"
test=> SET timezone = 'UTC';
SET
test=> INSERT INTO my_tbl (my_timestamp) VALUES (NOW());
INSERT 0 1

यह 100% सही नहीं है, लेकिन यह एक मजबूत पर्याप्त एंटी-फ़ुटशूटिंग उपाय प्रदान करता है जो सुनिश्चित करता है कि डेटा पहले से ही यूटीसी में परिवर्तित हो गया है। यह कैसे करना है, इस पर बहुत सारी राय है, लेकिन यह मेरे अनुभव से व्यवहार में सबसे अच्छा लगता है।

डेटाबेस टाइम ज़ोन हैंडलिंग की आलोचनाएँ काफी हद तक सही हैं (बहुत सी डेटाबेस हैं जो इसे बड़ी अक्षमता से संभालते हैं), हालांकि टाइमस्टैम्प और टाइमज़ोन की पोस्टग्रेज़क्यूएल की हैंडलिंग बहुत बढ़िया (कुछ "सुविधाओं" के बावजूद यहाँ और वहाँ है)। उदाहरण के लिए, ऐसी एक विशेषता:

-- Make sure we're all working off of the same local time zone
test=> SET timezone = 'America/Los_Angeles';
SET
test=> SELECT NOW();
              now              
-------------------------------
 2011-05-27 15:47:58.138995-07
(1 row)

test=> SELECT NOW() AT TIME ZONE 'UTC';
          timezone          
----------------------------
 2011-05-27 22:48:02.235541
(1 row)

ध्यान दें कि AT TIME ZONE 'UTC'समय क्षेत्र की जानकारी स्ट्रिप्स और TIMESTAMP WITHOUT TIME ZONEआपके लक्ष्य के संदर्भ के फ्रेम ( UTC) का उपयोग करके एक रिश्तेदार बनाती है ।

जब एक अधूरी से परिवर्तित TIMESTAMP WITHOUT TIME ZONEएक करने के लिए TIMESTAMP WITH TIME ZONE, लापता समय क्षेत्र अपने कनेक्शन से विरासत में मिली है:

test=> SET timezone = 'America/Los_Angeles';
SET
test=> SELECT EXTRACT(TIMEZONE_HOUR FROM NOW());
 date_part 
-----------
        -7
(1 row)
test=> SELECT EXTRACT(TIMEZONE_HOUR FROM TIMESTAMP WITH TIME ZONE '2011-05-27 22:48:02.235541');
 date_part 
-----------
        -7
(1 row)

-- Now change to UTC    
test=> SET timezone = 'UTC';
SET
-- Create an absolute time with timezone offset:
test=> SELECT NOW();
              now              
-------------------------------
 2011-05-27 22:48:40.540119+00
(1 row)

-- Creates a relative time in a given frame of reference (i.e. no offset)
test=> SELECT NOW() AT TIME ZONE 'UTC';
          timezone          
----------------------------
 2011-05-27 22:48:49.444446
(1 row)

test=> SELECT EXTRACT(TIMEZONE_HOUR FROM NOW());
 date_part 
-----------
         0
(1 row)

test=> SELECT EXTRACT(TIMEZONE_HOUR FROM TIMESTAMP WITH TIME ZONE '2011-05-27 22:48:02.235541');
 date_part 
-----------
         0
(1 row)

तल - रेखा:

  • उपयोगकर्ता के टाइम ज़ोन को नामित लेबल (उदा America/Los_Angeles) के रूप में संग्रहीत करें और UTC (जैसे -0700) से ऑफसेट न करें
  • जब तक एक गैर-शून्य ऑफसेट को संग्रहीत करने के लिए एक सम्मोहक कारण नहीं है, तब तक सब कुछ के लिए यूटीसी का उपयोग करें
  • इनपुट त्रुटि के रूप में सभी गैर-शून्य यूटीसी समय का इलाज करें
  • कभी भी सापेक्ष और पूर्ण टाइमस्टैम्प का मिश्रण और मिलान न करें
  • भी उपयोग UTCके रूप में timezoneडेटाबेस यदि संभव हो तो में

रैंडम प्रोग्रामिंग लैंग्वेज नोट: पाइथन का datetimeडेटा प्रकार निरपेक्ष बनाम सापेक्ष समय के बीच अंतर को बनाए रखने में बहुत अच्छा है (यद्यपि आप जब तक आप इसे PyTZ जैसी लाइब्रेरी के साथ पूरक नहीं करते हैं, तब तक निराशा होती है )।


संपादित करें

मुझे सापेक्ष बनाम पूर्ण के बीच के अंतर को थोड़ा और अधिक स्पष्ट करने दें।

किसी घटना को रिकॉर्ड करने के लिए निरपेक्ष समय का उपयोग किया जाता है। उदाहरण: "उपयोगकर्ता 123 लॉग इन" या "एक स्नातक समारोह 2011-05-28 2:00 पीएसटी पर शुरू होता है।" अपने स्थानीय समय क्षेत्र के बावजूद, यदि आप उस स्थान पर टेलीपोर्ट कर सकते हैं जहां घटना हुई है, तो आप हो रही घटना को देख सकते हैं। किसी डेटाबेस में अधिकांश समय डेटा निरपेक्ष है (और इसलिए TIMESTAMP WITH TIME ZONEआदर्श रूप से +0 ऑफसेट के साथ होना चाहिए और एक पाठ लेबल विशेष टाइमज़ोन को नियंत्रित करने वाले नियमों का प्रतिनिधित्व करता है - ऑफ़सेट नहीं)।

एक रिश्तेदार घटना एक निश्चित-समय-निर्धारित समय क्षेत्र के दृष्टिकोण से किसी चीज़ के समय को रिकॉर्ड या शेड्यूल करना होगा। उदाहरण: "हमारे व्यवसाय के दरवाजे सुबह 8 बजे खुलते हैं और रात 9 बजे बंद होते हैं", चलो हर सोमवार को सुबह 7 बजे साप्ताहिक नाश्ते की बैठक के लिए मिलते हैं, "या" हर शाम 8 बजे हैलोवीन। " सामान्य तौर पर, घटनाओं के लिए टेम्प्लेट या कारखाने में सापेक्ष समय का उपयोग किया जाता है, और निरपेक्ष समय का उपयोग लगभग सभी चीजों के लिए किया जाता है। एक दुर्लभ अपवाद है जो इंगित करने के लायक है जो सापेक्ष समय के मूल्य को चित्रित करना चाहिए। भविष्य की घटनाओं के लिए जो भविष्य में काफी दूर हैं जहां उस समय के बारे में अनिश्चितता हो सकती है जिस समय कुछ हो सकता है, एक रिश्तेदार टाइमस्टैम्प का उपयोग करें। यहाँ एक वास्तविक दुनिया उदाहरण है:

यह वर्ष 2004 है मान लीजिए और आप अमेरिका के पश्चिमी तट (यानी को दोपहर 1 बजे से 2008 में 31 अक्टूबर एक प्रसव का समय निर्धारित करने की जरूरत है America/Los_Angeles/ PST8PDT)। यदि आप उस समय का उपयोग करते हुए संग्रहीत करते हैं ’2008-10-31 21:00:00.000000+00’::TIMESTAMP WITH TIME ZONE, तो वितरण को दोपहर 2 बजे दिखाया जाता है क्योंकि अमेरिकी सरकार ने 2005 के ऊर्जा नीति अधिनियम को पारित किया था जिसने दिन के समय की बचत के समय को नियंत्रित करने वाले नियमों को बदल दिया था। 2004 में जब डिलीवरी का समय निर्धारित किया गया था, तो यह तारीख 10-31-2008पैसिफिक स्टैंडर्ड टाइम ( +8000) थी, लेकिन वर्ष 2005 में शुरू होने वाले + टाइमज़ोन डेटाबेस ने माना कि 10-31-2008पैसिफिक डेलाइट सेविंग टाइम (होगा)+0700)। समय क्षेत्र के साथ एक रिश्तेदार टाइमस्टैम्प स्टोर करने से एक सही डिलीवरी शेड्यूल हो जाता है क्योंकि एक रिश्तेदार टाइमस्टैम्प कांग्रेस की बीमार-सूचना छेड़छाड़ के लिए प्रतिरक्षा है। जहाँ शेड्यूलिंग चीज़ों के लिए सापेक्ष बनाम निरपेक्ष समय का उपयोग करने के बीच की कटऑफ एक अस्पष्ट रेखा है, लेकिन मेरे अंगूठे का नियम यह है कि भविष्य में किसी भी चीज़ के लिए 3-6mo से अधिक समय के लिए शेड्यूलिंग करना रिश्तेदार टाइमस्टैम्प का उपयोग करना चाहिए (अनुसूचित = निरपेक्ष बनाम नियोजित =) रिश्तेदार ???)।

अन्य / रिश्तेदार समय के अंतिम प्रकार है INTERVAL। उदाहरण: "उपयोगकर्ता लॉग करने के 20 मिनट बाद सत्र समाप्त हो जाएगा"। एक INTERVALसही ढंग से या तो पूर्ण timestamps (साथ इस्तेमाल किया जा सकता TIMESTAMP WITH TIME ZONE) या रिश्तेदार timestamps ( TIMESTAMP WITHOUT TIME ZONE)। यह कहना भी उतना ही सही है, "एक सफल सत्र (login_utc + session_duration) के बाद एक उपयोगकर्ता सत्र 20 मिनट की अवधि समाप्त हो जाता है" या "हमारी सुबह की नाश्ते की बैठक केवल 60 मिनट (आवर्ती_स्टार्ट_टाइम + मीटिंग_ लंबित)" हो सकती है।

भ्रम की अंतिम बिट्स: DATE, TIME, TIME WITHOUT TIME ZONEऔर TIME WITH TIME ZONEसभी रिश्तेदार डेटा प्रकार हैं। उदाहरण के लिए: '2011-05-28'::DATEआपके पास कोई समय क्षेत्र की जानकारी नहीं होने के कारण एक रिश्तेदार तिथि का प्रतिनिधित्व करता है जिसका उपयोग मध्यरात्रि को पहचानने के लिए किया जा सकता है। इसी तरह, '23:23:59'::TIMEसापेक्ष है क्योंकि आप या तो समय क्षेत्र या DATEसमय द्वारा प्रतिनिधित्व नहीं जानते हैं । यहां तक ​​कि '23:59:59-07'::TIME WITH TIME ZONE, आप नहीं जानते कि क्या DATEहोगा। और अंत में, DATEसमय क्षेत्र वास्तव में नहीं है DATE, यह एक है TIMESTAMP WITH TIME ZONE:

test=> SET timezone = 'America/Los_Angeles';
SET
test=> SELECT '2011-05-11'::DATE AT TIME ZONE 'UTC';
      timezone       
---------------------
 2011-05-11 07:00:00
(1 row)

test=> SET timezone = 'UTC';
SET
test=> SELECT '2011-05-11'::DATE AT TIME ZONE 'UTC';
      timezone       
---------------------
 2011-05-11 00:00:00
(1 row)

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


2
यदि आप सही समय पर उपयोगकर्ता के टाइमस्टैम्प को पोस्टग्रेजेल बता देते हैं, तो पोस्टग्रैसिकल पर्दे के पीछे भारी लिफ्टिंग करेगा। इसे अपने आप में परिवर्तित करना केवल उधार लेने की परेशानी है।
सेठ रॉबर्टसन

1
@ सीन - अपने चेक की कमी के साथ, आप कभी भी बिना टाइमस्टैम्प कैसे डालें set timezone to 'UTC'? आप जानते हैं कि यूटीसी में सभी टाइमज़ोन-जागरूक तिथियों को आंतरिक रूप से संग्रहीत किया जाता है ?

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

6
@ सीन: लेकिन, जैसा कि जैक इंगित करता है, सभी टाइमज़ोन-जागरूक टाइमस्टैम्प मूल रूप से यूटीसी में आंतरिक रूप से संग्रहीत होते हैं और उपयोग किए जाने पर आपके स्थानीय टाइमज़ोन में परिवर्तित हो जाते हैं; प्रभावी रूप से, अर्क (... से टाइमज़ोन ...) तब कनेक्शन के स्थानीय समयक्षेत्र में जो भी होगा वह हमेशा वापस आ जाएगा: इसका कोई संबंध नहीं है कि टाइमस्टैम्प "संग्रहीत" कैसे किया गया था। अलग तरीके से कहें, तो समय क्षेत्र किसी भी प्रकार का हिस्सा नहीं है, और इसे संग्रहीत नहीं किया जा सकता है: "समय क्षेत्र के साथ" सिर्फ एक संपत्ति है कि डेटा को अन्य प्रकारों के साथ बातचीत करते समय कैसे परिवर्तित किया जाएगा। इस प्रकार डेटा में टाइमज़ोन का कोई प्रतिनिधित्व नहीं है, पाठ या अन्यथा।
जे। फ्रीमैन -सौरिक-

@ JayFreeman-saurik-: आप बिल्कुल सही हैं। '' CHECK () '' संभवतः डोडी कोड से बचाव के लिए एक एंटी-फ़ुटशूटिंग उपाय के रूप में है। यह सुनिश्चित करना कि डेटा यूटीसी ऑन राइट है एक मामूली गारंटी प्रदान करता है कि कोड के माध्यम से सोचा गया था या निष्पादन वातावरण सही ढंग से सेटअप है।
सीन

58

शॉन का उत्तर अत्यधिक जटिल और भ्रामक है।

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

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

पसंद का उपयोग करें 3. हमेशा "समय क्षेत्र के साथ" का उपयोग करें जब तक कि कोई विशेष कारण न हो।


10
डेविड ई। व्हीलर, एक प्रमुख पोस्टग्रैज विशेषज्ञ, अपनी पोस्टिंग के अनुसार आपके आकलन से सहमत होंगे, ऑलवेज यूज टाइमस्टैप विथ टाइम टोन
बेसिल बोर्के

2
क्या होगा यदि आपके पास ब्राउज़र यूटीसी समय टिकट को स्थानीय समय क्षेत्र में बदल देगा? तो, db रूपांतरण नहीं करेगा और केवल UTC सम्‍मिलित करेगा। क्या "समय क्षेत्र के बिना" स्वीकार्य होगा?
dman

5

मेरी प्राथमिकता विकल्प 3 की ओर है, क्योंकि पोस्टग्रेज तब आपके लिए टाइमज़ोन के सापेक्ष कार्यबल के अल ओट को कर सकता है, जबकि अन्य दो के साथ आपको स्वयं ऐसा करना होगा। जब तक आप लाखों रिकॉर्ड्स की बात नहीं कर रहे हों, तब तक टाइमस्टैम्प के भंडारण के अतिरिक्त भंडारण ओवरहेज़ वास्तव में नगण्य है, जब तक कि आप लाखों रिकॉर्ड की बात नहीं कर रहे हों।


19
गलत। कोई ओवरहेड नहीं है ... पोस्टग्रेज समय क्षेत्र को स्टोर नहीं करता है ('ऑफसेट' सही शब्द है, टाइम ज़ोन नहीं है, वैसे)। TIMESTAMP WITH TIME ZONEनाम भ्रामक है। इसका वास्तव में अर्थ है "सम्मिलित करने / अद्यतन करने और उपयोग करने के लिए किसी भी निर्दिष्ट ऑफसेट पर ध्यान देना और उस समय को UTC में समायोजित करने के लिए ऑफ़सेट"। TIMESTAMP WITHOUT TIME ZONEनाम का अर्थ है "उपेक्षा किसी भी ऑफसेट कि सम्मिलित / अपडेट करने के दौरान उपस्थित हो सकता है, समायोजन के लिए कोई ज़रूरत नहीं के साथ यूटीसी में होने के रूप में दिनांक और समय भागों पर विचार"। डॉक्स को ध्यान से पढ़ें ।
बेसिल बॉर्क

1
@BasilBourque जानकारी के इस टुकड़े के लिए धन्यवाद। अविश्वसनीय रूप से उपयोगी। अन्य लोगों के लिए यह डॉक से लाईन कहती है, "एक ऐसे शाब्दिक में जो समय क्षेत्र के बिना टाइमस्टैम्प के लिए निर्धारित किया गया है, PostgreSQL चुपचाप किसी भी समय क्षेत्र संकेत की अनदेखी करेगा। अर्थात, परिणामी दिनांक या समय फ़ील्ड से व्युत्पन्न है। इनपुट मूल्य, और समय क्षेत्र के लिए समायोजित नहीं किया गया है। "
एडन रॉसवुड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.