Tarih saati veya zaman damgası alanı kullanmanızı önerir misiniz ve neden (MySQL kullanarak)?
Sunucu tarafında PHP ile çalışıyorum.
Tarih saati veya zaman damgası alanı kullanmanızı önerir misiniz ve neden (MySQL kullanarak)?
Sunucu tarafında PHP ile çalışıyorum.
Yanıtlar:
MySQL'deki zaman damgaları genellikle kayıtlardaki değişiklikleri izlemek için kullanılır ve genellikle kayıt her değiştiğinde güncellenir. Belirli bir değeri saklamak istiyorsanız datetime alanı kullanmalısınız.
UNIX zaman damgası veya yerel bir MySQL datetime alanı kullanma arasında karar vermek istediğinizi düşünüyorsanız, yerel biçime gidin. MySQL içinde hesaplamaları bu şekilde yapabilirsiniz
("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")
ve ("SELECT UNIX_TIMESTAMP(my_datetime)")
PHP ile çalışmak istiyorsanız kaydı sorguladığınızda değerin biçimini UNIX zaman damgasına dönüştürmek kolaydır .
DATETIME
bir tarihi (bir takvimde bulunduğu gibi) ve bir zamanı (bir duvar saatinde görülebileceği gibi) TIMESTAMP
temsil ederken , zaman içinde iyi tanımlanmış bir noktayı temsil etmesidir. Uygulamanız saat dilimlerini işlerse, bu çok önemli olabilir. '2010-09-01 16:31:00' ne kadar zaman önceydi? Hangi saat diliminde olduğunuza bağlı. Benim için sadece birkaç saniye önceydi, çünkü sizin için gelecekte bir zamanı temsil edebilir. '1970-01-01 00:00:00 UTC'den beri 1283351460 saniye dersem, tam olarak hangi konuda konuştuğumu biliyorsun. (Aşağıdaki Nir'nun mükemmel cevabına bakınız). [Dezavantajı: geçerli aralık].
MySQL 5 ve üzeri sürümlerde , TIMESTAMP değerleri depolama için geçerli saat diliminden UTC'ye dönüştürülür ve geri almak için UTC'den geçerli saat dilimine dönüştürülür. (Bu, yalnızca TIMESTAMP veri türü için geçerlidir, DATETIME gibi diğer türler için geçerli değildir .)
Varsayılan olarak, her bağlantı için geçerli saat dilimi sunucunun saatidir. Saat dilimi, MySQL Server Saat Dilimi Desteğinde açıklandığı gibi bağlantı başına ayarlanabilir .
Her zaman DATETIME alanlarını satır meta verileri (oluşturulduğu veya değiştirildiği tarih) dışında bir şey için kullanırım.
MySQL belgelerinde belirtildiği gibi :
DATETIME türü, hem tarih hem de saat bilgileri içeren değerlere ihtiyacınız olduğunda kullanılır. MySQL, DATETIME değerlerini alır ve 'YYYY-AA-GG SS: DD: SS' biçiminde görüntüler. Desteklenen aralık '1000-01-01 00:00:00' ila '9999-12-31 23:59:59' şeklindedir.
...
TIMESTAMP veri türünün aralığı '1970-01-01 00:00:01' UTC ila '2038-01-09 03:14:07' UTC'dir. MySQL sürümüne ve sunucunun çalıştığı SQL moduna bağlı olarak değişen özelliklere sahiptir.
Genel kullanımda TIMESTAMP'lerin alt sınırına ulaşma olasılığınız yüksektir - örn. Doğum tarihinin saklanması.
new Date().getTime()
zaten 64 bitlik bir değer verir.
Örnekler aşağıda göstermek TIMESTAMP
tarih türü değiştirdikten sonra değerleri değişti time-zone to 'america/new_york'
nerede DATETIME
değişmez.
mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name | Value |
+------------------+---------------------+
| system_time_zone | India Standard Time |
| time_zone | Asia/Calcutta |
+------------------+---------------------+
mysql> create table datedemo(
-> mydatetime datetime,
-> mytimestamp timestamp
-> );
mysql> insert into datedemo values ((now()),(now()));
mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime | mytimestamp |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 14:11:09 |
+---------------------+---------------------+
mysql> set time_zone="america/new_york";
mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime | mytimestamp |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 04:41:09 |
+---------------------+---------------------+
Cevabımı makaleye dönüştürdüm, böylece daha fazla insan bu yararlı bulabilir, MySQL: Datetime Versus Zaman Damgası Veri Türleri .
DATETIME
zaman dilimi değişikliği ile etkili zaman değişti, değişmedi, TIMESTAMP
ancak insan temsili değişti.
set time_zone="america/new_york"
;
Ana fark, TIMESTAMP time_zone
ayardan etkilenirken DATETIME sabit olmasıdır .
Bu nedenle, yalnızca zaman dilimleri arasında senkronize kümelere sahip olduğunuzda veya gelecekte olabileceğinde önemlidir.
Daha basit bir deyişle: Avustralya'da bir veritabanım varsa ve Amerika'da bir veritabanını senkronize etmek / doldurmak için bu veritabanının bir dökümünü alırsam, TIMESTAMP, yeni saat dilimindeki olayın gerçek zamanını yansıtacak şekilde güncellenir, DATETIME yine de o saat dilimindeki etkinliğin saatini yansıtır .
TIMESTAMP'ın kullanılması gereken yerlerde kullanılan DATETIME'ın harika bir örneği, sunucularının saat dilimleri arasında ne zaman gerçekleştiğinden asla emin olamadığı Facebook'tur. Bir keresinde mesajın gönderilmesinden önce mesajlara cevap verdiğimi söyleyen bir konuşma yaptım. (Bu, elbette, zamanlar senkronize olmaktan ziyade yayınlanıyorsa, mesajlaşma yazılımındaki kötü saat dilimi çevirisinden de kaynaklanmış olabilir.)
Bu kararı semantik bir temelde alıyorum.
Zaman içinde (az ya da çok) sabit bir noktayı kaydetmem gerektiğinde zaman damgası kullanıyorum. Örneğin, veritabanına bir kayıt eklendiğinde veya bazı kullanıcı eylemleri gerçekleştiğinde.
Tarih / saat isteğe bağlı olarak ayarlanıp değiştirilebildiğinde datetime alanı kullanıyorum. Örneğin, bir kullanıcı daha sonra randevuları değiştirebiliyorsa.
Ne DATETIME ne de TIMESTAMP alanı kullanmanızı öneririm . Belirli bir günü bir bütün olarak (doğum günü gibi) temsil etmek istiyorsanız, bir DATE türü kullanın, ancak bundan daha spesifik iseniz, muhtemelen bir ünitenin aksine gerçek bir anı kaydetmek istersiniz. zaman (gün, hafta, ay, yıl). DATETIME veya TIMESTAMP kullanmak yerine, bir BIGINT kullanın ve çağdan bu yana geçen milisaniye sayısını saklayın (Java kullanıyorsanız System.currentTimeMillis ()). Bunun birkaç avantajı vardır:
Bu sorun, bir para değerini (yani 1,99 $) bir veritabanında nasıl depolamanız gerektiği ile yakından ilgilidir. Bir Ondalık mı yoksa veritabanının Para türünü mü yoksa tüm Double'lerin en kötüsünü mü kullanmalısınız? Bu seçeneklerin 3 tanesi de yukarıda listelenen aynı nedenlerden birçoğu için korkunç. Çözüm, paranızın değerini BIGINT kullanarak sentlerde saklamak ve sonra değeri kullanıcıya gösterdiğinizde sentleri dolara dönüştürmektir. Veritabanının işi verileri saklamak ve bu verileri yorumlamamaktır. Veritabanlarında (özellikle Oracle) gördüğünüz tüm bu süslü veri türleri çok az şey ekler ve sizi satıcı kilitlemesine doğru başlatır.
TIMESTAMP, DATETIME için 4 bayt ve 8 bayttır.
http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
Ancak scronide'ın 1970 yılının alt sınırına sahip olduğu gibi. Gelecekte olabilecek her şey için harika;)
TIMESTAMP, DATETIME için dört bayt ve sekiz bayttır.
Zaman damgaları da veritabanında daha hafiftir ve daha hızlı dizine eklenir.
DATETIME türü, hem tarih hem de saat bilgileri içeren değerlere ihtiyacınız olduğunda kullanılır. MySQL, DATETIME değerlerini alır ve 'YYYY-AA-GG SS: DD: SS' biçiminde görüntüler. Desteklenen aralık '1000-01-01 00:00:00 ′ ila' 9999-12-31 23:59:59 ′ 'dir.
TIMESTAMP veri türünün aralığı '1970-01-01 00:00:01 ′ UTC ila' 2038-01-09 03:14:07 ′ UTC'dir. MySQL sürümüne ve sunucunun çalıştığı SQL moduna bağlı olarak değişen özelliklere sahiptir.
Gerçekten uygulamaya bağlıdır.
Sanghai'de bir randevu için New York'ta bir sunucuya bir kullanıcı tarafından bir zaman damgası ayarlamayı düşünün. Şimdi kullanıcı Sanghai'ye bağlandığında, Tokyo'daki yansıtılmış bir sunucudan aynı randevu zaman damgasına erişir. Randevuyu Tokyo saatinde, orijinal New York döneminden ofset görecek.
Dolayısıyla, randevu veya zamanlama gibi kullanıcı zamanını temsil eden değerler için datetime daha iyidir. Kullanıcının, sunucu ayarlarından bağımsız olarak istenen tarih ve saati tam olarak kontrol etmesini sağlar. Ayarlanan saat, sunucunun saat dilimi, kullanıcının saat dilimi veya gün ışığından yararlanma saatinin hesaplanma biçimindeki değişikliklerden etkilenmeyen ayarlanan saattir (evet, değişir).
Öte yandan, ödeme işlemleri, tablo değişiklikleri veya günlük kaydı gibi sistem saatini temsil eden değerler için her zaman zaman damgalarını kullanın. Sistem, sunucuyu başka bir saat dilimine taşıdığından veya farklı saat dilimlerindeki sunucular arasında karşılaştırma yaparken etkilenmeyecektir.
Zaman damgaları da veritabanında daha hafiftir ve daha hızlı dizine eklenir.
Herhangi bir yeni ön uç çerçevesi (Açısal 1/2, tepki, Vue, ...) UTC tarih saatinizi kolayca ve otomatik olarak yerel saate dönüştürebilir.
Bunlara ek olarak:
(Sunucularınızın saat dilimini değiştirme olasılığınız yoksa)
AngularJs ile örnek
// back-end: format for angular within the sql query
SELECT DATE_FORMAT(my_datetime, "%Y-%m-%dT%TZ")...
// font-end Output the localised time
{{item.my_datetime | date :'medium' }}
Tüm yerelleştirilmiş saat biçimi burada bulunabilir: https://docs.angularjs.org/api/ng/filter/date
SET time_zone = '+0:00';
UTC için.
Bir timestamp
alan özel bir durumdur datetime
alanında. timestamp
Özel özelliklere sahip sütunlar oluşturabilirsiniz ; oluşturma ve / veya güncelleme ile kendini güncelleyecek şekilde ayarlanabilir.
"Büyük" veritabanı terimleriyle, timestamp
üzerinde birkaç özel durum tetikleyicisi vardır.
Doğru olanın ne olduğu tamamen ne yapmak istediğinize bağlıdır.
TIMESTAMP her zaman UTC'dir (yani, 1970-01-01'den beri geçen saniye, UTC'de) ve MySQL sunucunuz bunu otomatik olarak bağlantı saat dilimi tarih / saatine dönüştürür. Uzun vadede, TIMESTAMP gidilecek yoldur, çünkü geçici verilerinizin her zaman UTC'de olacağını bilirsiniz. Örneğin, farklı bir sunucuya taşınırsanız veya sunucunuzdaki saat dilimi ayarlarını değiştirirseniz, tarihlerinizi bozmazsınız.
Not: varsayılan bağlantı saat dilimi sunucu saat dilimidir, ancak bu oturum başına değiştirilebilir (bkz. SET time_zone = ...
) (Bkz. ).
DATETIME, TIMESTAMP ve DATE karşılaştırması
Bu [.fraksiyon] nedir?
Kaynaklar:
MySQL ve PHP ile çalışırken daima bir Unix zaman damgası kullanırdım. Bunun ana nedeni , PHP'deki varsayılan tarih yönteminin parametre olarak bir zaman damgası kullanmasıdır, bu nedenle ayrıştırma gerekmez.
PHP'de geçerli Unix zaman damgasını almak için sadece time();
ve MySQL'de yapın SELECT UNIX_TIMESTAMP();
.
MySQL'de tablo sütunlarınızı oluştururken aşağıdaki satırlar boyunca bir şeyler kullanabileceğinizi belirtmek gerekir:
on update CURRENT_TIMESTAMP
Bu, bir satırı değiştirdiğiniz her örnekte saati güncelleyecektir ve bazen depolanan son düzenleme bilgileri için çok yararlı olacaktır. Ancak bu yalnızca zaman damgasıyla çalışır, tarih saatiyle değil.
Deneyimlerime göre, eklemenin yalnızca bir kez gerçekleştiği bir tarih alanı istiyorsanız ve söz konusu alanda herhangi bir güncelleme veya başka bir işlem yapmak istemiyorsanız, tarih saatiyle devam edin .
Örneğin, KAYIT TARİHİ alanına user
sahip bir tablo düşünün . Bu tabloda, belirli bir kullanıcının son giriş zamanını bilmek istiyorsanız , alanın güncellenmesi için zaman damgası türünde bir alana gidin .user
Tabloyu phpMyAdmin'den oluşturuyorsanız , varsayılan ayar bir satır güncellemesi gerçekleştiğinde zaman damgası alanını güncelleyecektir. Dosya damgası zaman satırınız satır güncellemesiyle güncellenmiyorsa, zaman damgası alanının otomatik olarak güncellenmesini sağlamak için aşağıdaki sorguyu kullanabilirsiniz .
ALTER TABLE your_table
MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
Zaman damgası veri türü, tarih ve saati saklar, ancak tarih biçiminde olduğu gibi geçerli saat dilimi biçiminde değil UTC biçiminde saklar. Ve veri getirdiğinizde, zaman damgası bunu tekrar geçerli saat dilimine dönüştürür.
ABD'de olduğunuzu ve ABD'nin saat dilimi olan bir sunucudan veri aldığını varsayalım. Ardından tarih ve saati ABD saat dilimine göre alırsınız. Zaman damgası veri türü sütunu, satırı güncellendiğinde her zaman otomatik olarak güncellenir. Bu nedenle, belirli bir satırın en son ne zaman güncellendiğini izlemek yararlı olabilir.
Daha fazla bilgi için Timestamp Vs Datetime adlı blog gönderisini okuyabilirsiniz .
SET time_zone = '+0:00';
ne aldığınız / ayarladığınızdan emin olmak TIMESTAMP
ve değişebilecek sunucu time_zone varsayılanına bağlı olarak kaçınmak için saat dilimini her zaman (UTC) ile oturum düzeyinde tanımlayabilirsiniz .
Her zaman bir Unix zaman damgası kullanıyorum, özellikle çok sayıda datetime bilgisi ile uğraşırken, özellikle zaman dilimleri için ayarlamalar yaparken, tarihler eklerken / çıkarırken vb. Zaman damgalarını karşılaştırırken, bu, zaman diliminin karmaşık faktörlerini hariç tutar ve daha ağır tarih-saat ekleme / çıkarma yerine hafif aritmetik kullanmakta olduğunuz sunucu tarafı işlemenizdeki (uygulama kodu veya veritabanı sorguları olsun) kaynakları yedeklemenizi sağlar. fonksiyonlar.
Dikkate değer başka bir şey:
Bir uygulama oluşturuyorsanız, verilerinizin nasıl kullanılacağını asla bilemezsiniz. Diyelim ki, veri kümenizdeki bir grup kaydı, örneğin bir üçüncü taraf API'sından bir grup öğeyle karşılaştırmanız ve bunları kronolojik sıraya koymanız gerekiyorsa, Satırlarınız için Unix zaman damgaları. MySQL zaman damgalarını kullanmaya karar verseniz bile, sigorta olarak bir Unix zaman damgası saklayın.
Benim durumumda, UTC'yi her şey için bir saat dilimi olarak ayarladım: sistem, veritabanı sunucusu, vb. Müşterim başka bir saat dilimi gerektiriyorsa, uygulamada yapılandırırım.
Neredeyse her zaman datetime alanlarından ziyade zaman damgalarını tercih ederim, çünkü zaman damgaları zaman dilimini örtük olarak içerir. Dolayısıyla, uygulamaya farklı saat dilimlerinden kullanıcılardan erişileceği ve yerel saat dilimlerinde tarihleri ve saatleri görmelerini istediğiniz andan beri, bu alan türü, verilerin datetime alanlarına kaydedilmiş olduğundan daha kolay olmasını sağlar .
Bir artı olarak, veritabanının başka bir saat dilimine sahip bir sisteme taşınması durumunda, zaman damgalarını kullanarak kendime daha fazla güveniyorum. İki an arasındaki farkları hesaplarken, arada bir toplam zaman değişikliği ile 1 saat veya daha kısa bir hassasiyete ihtiyaç duyan olası sorunları söylememek.
Özetlemek gerekirse, zaman damgasının bu avantajlarına değer veriyorum:
Tüm bu nedenlerden dolayı, mümkün olduğunda UTC ve zaman damgası alanlarını seçiyorum. Ve baş ağrısından kaçınırım;)
warranties.expires_at
bugün gibi bir şey MySQL zaman damgası olamazdı.
Bir tabloda UPDATE ifadesi yaptığınızda zaman damgasının değişmesine dikkat edin. 'Name' (varchar), 'Age' (int) ve 'Date_ Added' (zaman damgası) sütunlarına sahip bir tablonuz varsa ve aşağıdaki DML ifadesini çalıştırırsanız
UPDATE table
SET age = 30
'Tarih_Görünüm' sütununuzdaki her bir değer geçerli zaman damgasına dönüştürülür.
ON UPDATE CURRENT_TIMESTAMP
Temel farklar:
TIMESTAMP, kayıtlardaki değişiklikleri izlemek ve kayıt her değiştiğinde güncellemek için kullanılır. DATETIME, kayıtlardaki değişikliklerden etkilenmeyen belirli ve statik değeri depolamak için kullanılır.
TIMESTAMP ayrıca TIME ZONE ile ilgili farklı ayarlardan da etkilenir. DATETIME sabit.
TIMESTAMP dahili olarak geçerli saat dilimini depolama için UTC'ye ve alma sırasında geçerli saat dilimine geri dönüştürdü. DATETIME bunu yapamaz.
TIMESTAMP desteklenen aralık: '1970-01-01 00:00:01 ′ UTC -' 2038-01-19 03:14:07 ′ UTC DATETIME desteklenen aralık: '1000-01-01 00:00:00 ′ -' 9999 -12-31 23:59:59 ′
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP | DATETIME |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP requires 4 bytes. | DATETIME requires 8 bytes. |
| Timestamp is the number of seconds that have elapsed since January 1, 1970 00:00 UTC. | DATETIME is a text displays 'YYYY-MM-DD HH:MM:SS' format. |
| TIMESTAMP supported range: ‘1970-01-01 00:00:01′ UTC to ‘2038-01-19 03:14:07′ UTC. | DATETIME supported range: ‘1000-01-01 00:00:00′ to ‘9999-12-31 23:59:59′ |
| TIMESTAMP during retrieval converted back to the current time zone. | DATETIME can not do this. |
| TIMESTAMP is used mostly for metadata i.e. row created/modified and audit purpose. | DATETIME is used mostly for user-data. |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
Zaman Damgası ve Tarih Saati arasındaki diğer bir fark, Zaman Damgası'nda varsayılan değeri NULL olarak ayarlayamazsınız.
CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
İlk sütun NULL değerini kabul edebilir.
TIMESTAMP'ın gereksiz tetikleyicileri kullanmadan şimdiki zamana göre kendini otomatik olarak güncelleme yeteneğinde eşsiz bir kullanışlılık buldum. TIMESTAMP'ın söylendiği gibi UTC olmasına rağmen bu sadece benim.
Farklı zaman dilimleri boyunca iz tutabilir, bu nedenle örneğin göreceli bir zaman göstermeniz gerekiyorsa, UTC saati istediğiniz şeydir.
En büyük fark
Tarih / saat dizine ekleme ile ilgili sorunları görmek için bu gönderiye bakın
datetime
Saat dilimleriyle ilgili birçok sorun ve hatayla karşılaştıktan sonra uygulamalarımda kullanmayı bıraktım . IMHO timestamp
kullanımı datetime
çoğu vakadan daha iyidir .
Ne zaman sordun? ve cevap '2019-02-05 21:18:30' gibi bir şey olarak geliyor, ki bu tamamlanmadı, tanımlanmamış cevap çünkü başka bir bölümden yoksun, hangi saat diliminde? Washington? Moskova? Pekin?
Zaman dilimi olmadan dat kullanmak, uygulamanızın yalnızca 1 zaman dilimi ile uğraştığı anlamına gelir, ancak zaman damgaları size datetime
farklı zaman dilimlerinde aynı tam noktayı gösterme esnekliği ve artıları sağlar.
Kullanmaktan pişmanlık duyacağınız datetime
ve verilerinizi zaman damgalarında saklamanızı isteyen bazı durumlar .
Müşterilerinizin rahatı için, onları matematik yapmadan ve tercih ettikleri zaman dilimlerine göre göstermek ve zamanı anlamlı saat dilimlerine dönüştürmek istemezsiniz. tek ihtiyacınız olan saat dilimini değiştirmek ve tüm uygulama kodunuz aynı olacaktır. (Aslında, uygulamanın başlangıcında her zaman saat dilimini tanımlamanız veya PHP uygulamaları durumunda işleme isteğinde bulunmanız gerekir)
SET time_zone = '+2:00';
kaldığınız ülkeyi değiştirdiniz ve farklı bir saat diliminde (gerçek verileri değiştirmeden) görürken verileri koruma çalışmalarınıza devam ediyorsunuz.
datetime
= uygulama 1 saat dilimini destekler (hem ekleme hem de seçme için)
timestamp
= uygulama herhangi bir saat dilimini destekler (hem ekleme hem de seçme için)
Bu cevap yalnızca zaman dilimleri söz konusu olduğunda esneklik ve zaman damgalarının kolaylığına vurgu yapmak içindir, sütun boyutu veya aralığı veya kesri gibi diğer farklılıkları kapsamaz .
date
ve diğer alanlar kullanılıyorsa timestamp
Filtrelenen veriler where
Timezone değişikliklerine uygun olmadığı için yeni bir soruna neden olacağını düşünüyorum .
date
sorguyu göndermeden önce saat dilimi sorununu sütunda düzeltmelidir .
A TIMESTAMP
4 bayt gerektirirken, a DATETIME
8 bayt gerektirir.
Unix zaman damgasını seviyorum, çünkü sayılara dönüşebilir ve sadece sayı hakkında endişelenebilirsiniz. Artı ekleme / çıkarma ve süreleri, vb olsun. Sonra herhangi bir formatta sonucu Tarih dönüştürün. Bu kod, bir belgeden zaman damgası ile geçerli saat arasında dakika olarak geçen süreyi öğrenir.
$date = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now - $result) / 60);
$min = round($unix_diff_min);