MySQL'de datetime veya zaman damgası veri türünü kullanmalı mıyım?


2686

Tarih saati veya zaman damgası alanı kullanmanızı önerir misiniz ve neden (MySQL kullanarak)?

Sunucu tarafında PHP ile çalışıyorum.


1
bununla ilgili bazı bilgiler vardır codeproject.com/Tips/1215635/MySQL-DATETIME-vs-TIMESTAMP
Waqleh

Başvurunuzun Şubat ayında kırılmasını istiyorsanız, 2038'de zaman damgası kullanın. Tarih aralığını kontrol edin.
Wilson Hauck

Yanıtlar:


1829

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 .


981
Önemli bir fark, DATETIMEbir tarihi (bir takvimde bulunduğu gibi) ve bir zamanı (bir duvar saatinde görülebileceği gibi) TIMESTAMPtemsil 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].
MattBianco

121
Başka bir fark: "yerel" tarih saatine sahip sorgular önbelleğe alınmayacak, ancak zaman damgasına sahip sorgular - olacaktır.
OZ_

39
"MySQL'deki zaman damgaları genellikle kayıtlardaki değişiklikleri izlemek için kullanılır" Bunun iyi bir yanıt olduğunu düşünmeyin. Zaman damgası, MattBianco ve Nir'un söylediklerinden çok daha güçlü ve karmaşıktır. Buna rağmen cevabın ikinci kısmı çok iyi. Blivet'in söylediği doğru ve iyi bir tavsiye.
santiagobasulto

10
Ayrıca 1 önemli not, DATETIME ve TIMESTAMP varsayılan değer olarak CURRENT_TIMESTAMP, NOW () kullanabilir, ancak varsayılan olarak 'DATE' kullanamaz, çünkü varsayılan olarak '0000-00-00' kullandığından, bu sorunu çözmek için U yazmalıdır. DATE mysql türüyle alana / col tarihini (zaman olmadan) eklemek için bu tabloya kendi tetikleyiciniz.
Arthur Kushman

14
@DavidHarkness: Documentation "Otomatik özellikleri belirtmek için DEFAULT CURRENT_TIMESTAMP ve ON UPDATE CURRENT_TIMESTAMP yan tümcelerini kullanın" dev.mysql.com/doc/refman/5.0/tr/timestamp-initialization.html
Plap

917

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 .


11
Bu OReilly sunumu bu konu için çok iyi (PDF üzgünüm) cdn.oreillystatic.com/en/assets/1/event/36/…
gcb

13
Ayrıca olayın doğası hakkında: - Bir video konferans (TIMESTAMP). Tüm katılımcılar saat dilimine göre ayarlanmış mutlak bir anı referans almalıdır. - Yerel bir görev zamanı (DATETIME), bu görevi 2014/03/31 09:00 de yapmalıyım, o gün New York veya Paris'te çalışıyorsam önemli değil. O gün olacağım yer olan yerel saatle 08: 00'de çalışmaya başlayacağım.
yucer

1
Sunucunun saat dilimini DEĞİŞTİRİRSE, o zaman TIMESTAMP değeri aynı kalacaktır ya da çok değişecek mi ??
Andrew

3
@ UTC olduğundan beri UTC olarak kalacaktır. Ancak geriye doğru dönüşüm "yeni" sunucu saat dilimine dönüşecektir.
nembleton

@yucer - Bu şekilde düşünmenizi tavsiye etmiyorum. Küresel ekonomide en tutarlı kullanım, depolama için tüm zamanları UTC'ye dönüştürmektir. Kural olarak, Datetime'ı UTC alanı olarak kabul edin. Bu, UTC'ye dönüştürme yapmak için tarih girilen tüm görevlere yük getirir, ancak uzun vadeli daha temiz bir tasarımdır. Tabii ki, bilgileri mevcut ayarlarına göre kullanıcıya sunun. Kullanıcı "Paris'te 09:00" girmek istiyorsa, Paris saatini ayarlamasını sağlayın, ardından 09:00 girin. Sonra New York'ta olan herkes telekonferans için zamanlarında uyanık olmaları gereken zamanı kolayca bulabilir.
ToolmakerSteve

524

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ı.


195
ayrıca bankacılık veya gayrimenkul iseniz üst limite kolayca vurabilirsiniz ... 30 yıllık ipotekler şimdi 2038 ötesine
Kip

16
Tabii ki 64 bit Unix zaman damgalarını kullanın. Örneğin, Java'da new Date().getTime()zaten 64 bitlik bir değer verir.
osa

5
DATETIME için +1: Satın alma ve fatura için Fiziksel Mağaza SQL Server'dan web sayfasında Sanal Mağaza için MySQL Server'a aktarılan veri akışımızda, bu veri türü Transact'te de mevcut olduğundan DATETIME, Değişiklik Tarih-Saati için daha iyidir -SQL. Ancak TIMESTAMP Transact-SQL'de başka bir şey ifade eder, MySQL TIMESTAMP DateTime benzer olsa da ROWVERSION gibi Binary'dir. Bu nedenle, iki DB'nin uyumluluğu için TIMESTAMP kullanımından kaçınıyoruz.
jacouh

10
Fikrim yok. Sadece MySQL'den çok daha büyük bir problem ve basit bir düzeltme yok: en.wikipedia.org/wiki/Year_2038_problem MySQL'in artık zaman damgasının 64 bit olduğunu ve her şeyin yolunda olacağını varsayabileceğine inanmıyorum. Donanımı kontrol etmezler.
scronide

5
Benim için yaptığım gibi, doğum zamanını biliyorsanız bir doğum tarihi bir DATETIME olabilir.
Kris Craig

322

Örnekler aşağıda göstermek TIMESTAMPtarih türü değiştirdikten sonra değerleri değişti time-zone to 'america/new_york'nerede DATETIMEdeğ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 .


55
Aslında, DATETIMEzaman dilimi değişikliği ile etkili zaman değişti, değişmedi, TIMESTAMPancak insan temsili değişti.
flindeberg

3
Bu komut MySQL 5.6'da çalışmıyor gibi görünüyor set time_zone="america/new_york";
Manjunath Reddy


2
@Flindeberg ile aynı fikirde. Zaman damgası, saat dilimi değişiminden sonra tarih saatini değil, doğru zamanı temsil eder
Nitin Bansal

193

Ana fark, TIMESTAMP time_zoneayardan 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.)


83
Bunun iyi bir düşünme yolu olduğunu düşünmüyorum. Sadece tüm tarihleri ​​UTC'de saklayıp işlerim ve ön ucun belirtilen zaman dilimine göre görüntülediğinden emin olurum. Bu yaklaşım basit ve öngörülebilirdir.
Kos

8
@Kos: UTC'de tüm tarihleri ​​depolamak ve işlemek tam olarak TIMESTAMP'ın dahili olarak ne yaptığını değil mi? (Daha sonra yerel saat diliminizi görüntülemek için dönüştürülüyor mu?)
karbokasyon

10
Benim yerel saat dilimi? DB'niz saat dilimimi nasıl bilebilir? ;-) Veritabanı ve kullanıcı arayüzü arasında normalde oldukça fazla işlem vardır. Yerelleştirmeyi yalnızca tüm işlemden sonra yaparım.
Kos

3
@Koz: veritabanım saat dilimini bilmiyor:! Ama zaman damgasını biliyor. Veritabanınız kendi saat dilimi ayarını bilir ve zaman damgasını yorumlarken / temsil ederken bunu uygular. Pekin'de 11 Aralık 2013 tarihinde 1:01 am, 11 Aralık 2013 tarihinde Sydney Avustralya'da 1:01 am ile aynı anda değil. Google: 'saat dilimleri' ve 'ana meridyen'.
ekerner

2
MySQL, TIMESTAMP değerlerini depolama için geçerli saat diliminden UTC'ye ve geri almak için UTC'den geçerli saat dilimine dönüştürür. (Bu, DATETIME gibi diğer türler için gerçekleşmez.) Dev.mysql.com/doc/refman/5.5/en/datetime.html
Mahdyfo

125

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.


zaman damgası sabit zaman noktası, Koordineli Evrensel Zaman tarih - bir bakış açısına göre, bir zaman referansı (ej saat dilimi yerel saat), olabilir .. Koordineli Yerel Zaman?
yucer

110

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:

  1. Satıcının kilitlenmesini önlersiniz. Hemen hemen her veritabanı tamsayıları benzer şekilde destekler. Başka bir veritabanına gitmek istediğinizi varsayalım. MySQL'in DATETIME değerleri arasındaki farklar ve Oracle'ın bunları nasıl tanımladığı konusunda endişe etmek ister misiniz? MySQL'in farklı sürümleri arasında bile, TIMESTAMPS farklı bir hassasiyet seviyesine sahiptir. Kısa bir süre önce MySQL zaman damgalarında milisaniyeyi destekledi.
  2. Saat dilimi sorunu yok. Burada farklı veri türlerine sahip zaman dilimlerinde neler olduğuna dair bazı içgörülü yorumlar var. Fakat bu ortak bir bilgi midir ve iş arkadaşlarınız bunu öğrenmek için zaman alacak mı? Öte yandan, bir BigINT'i bir java.util.Date'e dönüştürerek karıştırmak oldukça zor. Bir BIGINT kullanmak, zaman dilimleri ile ilgili birçok sorunun yol kenarına düşmesine neden olur.
  3. Aralıklar veya hassasiyet hakkında endişelenmeyin. Gelecekteki tarih aralıklarına göre kısaltılma konusunda endişelenmenize gerek yok (TIMESTAMP sadece 2038'e gidiyor).
  4. Üçüncü taraf araç entegrasyonu. Bir tamsayı kullanarak, üçüncü taraf araçların (örn. EclipseLink) veritabanıyla arabirim oluşturması önemsizdir. Her üçüncü taraf aracı, MySQL ile aynı "tarih-saat" anlayışına sahip olmayacaktır. Hazırda Bekleme'de, bu özel veri türlerini kullanıyorsanız bir java.sql.TimeStamp veya java.util.Date nesnesi kullanmanız gerekip gerekmediğini mi denemek istiyorsunuz? Temel veri türlerinizi kullanmak, üçüncü taraf araçlarla kullanımı önemsiz hale getirir.

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.


12
Bu çözümü seviyorum. 2038'de süresi dolan TIMESTAMP önemli bir sorundur. Bu o kadar da uzak değil!
Charlie Dalsass

4
@CharlieDalsass Şu anki yazılımın o zaman orada olacağını düşünüyor musunuz :-P
Habeeb Perwad

13
Milisaniye olarak saklanırsa verileri tarihe göre sorgulamayı zorlaştırır
Ali Saeed

4
Bu, taşınabilirliği ve kullanıcıları birden fazla saat diliminde veya kullanıcılardan farklı bir saat dilimindeki veritabanında işlemeyi önemsiyorsanız en iyi çözümdür. TIMESTAMP, kusurları tasarlamıyorsa gidilecek yol olabilir. Kırık çözümlerin daha erken oy kullanması çok kötü (yıllarca!).
Almanca

4
Mükemmel çözüm! Ve tam olarak haklısın "kilitli". Başkalarının "işi sizin için yapmasına" izin verme alışkanlığına sahip olduğunuzda, sizi programcı yapan bitleri ve parçaları kaybetmeye başlarsınız.
fmc

98

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;)


185
Gelecek, 2038-01-19 03:14:07 UTC'de sona erecek.
MattBianco

5
Bu aptalca. Ben TIMESTAMP türü "geleceğe hazır" olacağını düşündüm çünkü nispeten yeni. Farklı saat dilimlerinde her çalıştığınızda tarih saatini UTC'ye ve geri dönüşü rahatsız edemezsiniz. TIMESTAMP'i daha büyük yapmalıydım .. en az 1 byte daha büyük olmalılar. 32 bit hizalanmamasına rağmen 68 * 255 = 17340 yıl daha ekleyecektir.
Mart'ta NickSoft

10
TIMESTAMP'ın neden 2038'de bittiğini biliyor musunuz? Çünkü bu bir tamsayıdır ve tamsayıların sınırı 2147483647'dir. Bence bunun nedeni budur. Türünü varchar olarak değiştirir ve nasıl manipüle edileceğini değiştirirse, "geleceğe hazır" olacaktır.
vinsa

6
@vinsa, o zamana kadar geleceğin hazır olacağını düşünmüyorum. Y2K hatasını hala hatırlıyor musunuz? 2038 geliyor.
Pacerier

2
2038'e kadar MySQL (eğer hala mevcutsa) TIMESTAMP alanını 4 bayttan fazla kullanacak şekilde güncelleyecek ve daha geniş bir aralığa izin verecektir
the_nuts

95
  1. TIMESTAMP, DATETIME için dört bayt ve sekiz bayttır.

  2. Zaman damgaları da veritabanında daha hafiftir ve daha hızlı dizine eklenir.

  3. 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.

  1. TIMESTAMP, time_zone ayarından etkilenirken DATETIME sabittir.

6
# 4: Zaman damgasının zaman dilimi için sabit ve göreceli olmayan (tamamen agnostik) olduğu için zaman damgasını netleştirmeniz gerekirken, alma sırasında görüntülenen çıktı talep eden oturumun saat diliminden etkilenir. DATETIME her zaman kaydedildiği zaman dilimine bağlıdır ve her zaman bu bağlamda, şimdi uygulamaya düşen bir sorumluluk olarak düşünülmelidir.
Christopher McGowan

1
Mükemmel cevap. Bu cevaba eklemek için, değerleri '2038-01-09 03:14:07' ötesinde saklamaya çalışırsak, bir hata alırız veya '0000-00-00 00:00:00' olarak depolanır. Zaman aşımı değerleri (şifreleme amaçlı) olduğu için veritabanım için bu hatayı alıyordum.
KarthikS

Ayrıca, 5.5'in altındaki mysql sürümlerinde VARSAYILAN değeri olan DATETIME ile ilgili bir sorun var. dba.stackexchange.com/questions/132951/…
Velaro

47

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.


Uygulamanız sunucunun saat dilimine bağlı olmamalıdır. Bir uygulama HER ZAMAN herhangi bir sorgu göndermeden önce kullandığı veritabanı bağlantısı oturumunda saat dilimini seçmelidir. Bir bağlantı birden fazla kullanıcı arasında paylaşılıyorsa (ör: webapp), UTC'yi kullanın ve oluşturma tarafında saat dilimi dönüşümü yapın.
dolmen

42

2016 + : Mysql saat diliminizi UTC olarak ayarlamak ve DATETIME kullanmaktır:

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


8
Verileriniz sunucularınızın saat dilimi ayarlarına eklenmemelidir. Masanızın altında tek bir MySql kutunuz varsa, belki de sizin için çalışıyor
Jin

@Jin UTC, TIMESTAMP gibi saat dilimi anlamına gelmez. Tüm sunucularınız UTC'deyse sorun yoktur. 2000'li bir yapılandırmaya sahipseniz belki sizin için çalışmıyor.
Sebastien Horin

TIMESTAMP, gelecekte 64 bit değerine yükseltilebilir. O zaman artık sorun yok.
twicejr

Böyle bir şeyi yakalamak için tüm üçüncü taraf kitaplıklarını yüklemek de performans için o kadar büyük olamaz, değil mi? İstemci tarafı olduğu ve veritabanınızı etkilemediği göz önüne alındığında ... Yine de, yaptığınız her şey sunucu tarafı denetimleri gerektirecektir. Peki, resmin tamamını düşünmek , hız sorununa gerçekten yardımcı oluyor mu? - Bu kriterler bu arada biraz garip, hissediyorum. Sorguda zaman damgası alanlarını karşılaştırmak için bir dize kullanmak da oldukça garip geliyor. Bu aynı zamanda performansa da zarar vermeli, değil mi?
NoobishPro

1
Sunucunuzun time_zone uygulamanıza güvenmeyin. Bunun yerine her bir veritabanı bağlantısında kullanılacak saat_onunu tanımlayın: SET time_zone = '+0:00';UTC için.
dolmen

37

Bir timestampalan özel bir durumdur datetimealanı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.


6
Hayır, fark sadece "özel bir durum" değildir. Çünkü seansın zaman dilimlerini ayarlayan / sorgulayan değerler farklı şekilde dahil edilir.
dolmen

"Doğru olanın tam olarak ne yapmak istediğinize bağlı olduğunu" belirttiğiniz için memnunum. SE üzerinde, " Asla X yapmamalısın" veya "Her zaman Y yapmalısın" durumunu söyleyen çok fazla cevap var .
Agi Hammerthief

37

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. ).



24

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();.


6
-1 Aslında aşağıdaki cevabın daha iyi olduğunu düşünüyorum - datetime kullanmak, tarih işleme için MySQL'in içine daha fazla mantık aktarmanıza izin verir, ki bu çok yararlı olabilir.
Toby Hede

MySQL sıralamasında php daha yavaş gösteren kriterler var mı?
sdkfasldf

iyi, bazen strtotime kullanmak istemediğimizde kullanmak iyidir. (php5.3 dep)
Adam

Gerekirse sadece FROM_UNIXTIME kullanarak mantığı mysql'ye aktarabilirsiniz
inarilo

PHP uygulamalarında ve MySQL'de tüm Unix zaman damgalarını kullanıyordum, ancak yerel tarih / saat türleri olarak MySQL'de tarih ve saatleri saklamanın çok daha uygun olduğunu gördüm. Bu özellikle raporlama amacıyla ve sadece veri kümelerine göz atmak için kullanışlıdır. Zamanla, Unix zaman damgalarını kopyalamak / geçmek zorunda kaldığım için hayal kırıklığına uğradım. Performans ve diğer artıları / eksileri olduğuna eminim, ancak kullanım durumunuza bağlı olarak oldukça mikro optimizasyonlardan daha önemli olabilir.
DavidScherer

24

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.


17

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 usersahip 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;

15

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 .


Değerlerden SET time_zone = '+0:00';ne aldığınız / ayarladığınızdan emin olmak TIMESTAMPve 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 .
dolmen

14

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.


14

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:

  • uluslararası (çoklu zaman dilimi) uygulamalarında kullanıma hazır
  • zaman dilimleri arasında kolay taşıma
  • farkları hesaplamak oldukça kolay (sadece her iki zaman damgasını da çıkarın)
  • yaz dönemi giriş / çıkış tarihleri ​​hakkında endişelenme

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;)


20 Ocak 2038 geldiğinde başvurunuzu destekleyen kişi için zaman damgası verileri eğlenceli olacaktır. kene tock kene tock
Wilson Hauck

Zaman damgası türü daha sonra biraz artırılabilir ve olası değerler iki katına çıkarılabilir.
Roger Campanera

Teorinizi 'biraz artırmak' için test edin ve 1 Şubat 2038'i başarıyla depolayıp depolayamayacağınızı ve MySQL ile geri alıp alamayacağınızı görün. İşlemi tamamladığınızda tablo tanımınızı görelim. Muhtemelen Şubat 2038'de çok fazla mutsuz geçmiş tanıdıklarınız olacak.
Wilson Hauck

1
@WilsonHauck MySQL sürümünü 2038'den çok önce yükseltmeniz gerekecek. Ve bu uzatılmış TIMESTAMP, geçiş tarafından ele alınacaktır. Ayrıca, ipotekleri idare etmenin yanı sıra çok az uygulamanın şu anda 2038'i gerçekten önemsemesi gerekiyor.
dolmen

@ dolmen birçok profesyonel sınıf araç ve malzeme 20+ yıl garantilidir. Yani warranties.expires_atbugün gibi bir şey MySQL zaman damgası olamazdı.
alexw

13

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.


3
tablonuzu nasıl ayarladığınıza bağlı olarak bu davranışı kontrol edebilirsiniz. bakmak dev.mysql.com/doc/refman/5.5/en/timestamp-initialization.html
Charles Faiga

5
@CharlesFaiga Varsayılan davranış, başka bir sütun güncellendiğinde zaman damgasının güncellenmesidir. Zaman damgasının orijinal değerini korumasını istiyorsanız bunu açıkça kapatmanız gerekir
Lloyd Banks

O nedir ?! zaman damgası sütununuON UPDATE CURRENT_TIMESTAMP
Muhasebeci م

Bu, tablo oluştururken açık bir şekilde etkinleştirmeniz gereken bir özelliktir .
dolmen

13

Bu Maddeden alınan referans:

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 ′


11
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
|                                       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.                                   |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+

10

Zaman Damgası ve Tarih Saati arasındaki diğer bir fark, Zaman Damgası'nda varsayılan değeri NULL olarak ayarlayamazsınız.


8
Açıkçası yanlış. İşte bir örnek: CREATE TABLE t2 ( ts1 TIMESTAMP NULL, ts2 TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP); İlk sütun NULL değerini kabul edebilir.
Ormoz

10

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.


9

En büyük fark

  • zaman damgası bir INDEX's - çalışır
  • Bir INDEX DateTime üzerinde bulunuyor - mu değil iş

Tarih / saat dizine ekleme ile ilgili sorunları görmek için bu gönderiye bakın


6
Sütun değerine dayalı bir işlev seçerseniz her ikisinde de aynı sorun vardır ve her ikisi de dizine eklenebilir.
Marcus Adams

4
Dizin zaman damgası üzerinde çalışıyor ve datetime üzerinde çalışmıyor mu? Bu gönderilerden yanlış sonuçlar çıkardınız.
Salman A

9

datetimeSaat dilimleriyle ilgili birçok sorun ve hatayla karşılaştıktan sonra uygulamalarımda kullanmayı bıraktım . IMHO timestampkullanı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 datetimefarklı zaman dilimlerinde aynı tam noktayı gösterme esnekliği ve artıları sağlar.

Kullanmaktan pişmanlık duyacağınız datetimeve verilerinizi zaman damgalarında saklamanızı isteyen bazı durumlar .

  1. 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';
  2. 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.

  3. dünyanın her yerinden farklı müşterilerden gelen verileri kabul edersiniz, her biri zamanı saat dilimine ekler.

Kısacası

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 .


bir tabloda kullanılan alanlar dateve diğer alanlar kullanılıyorsa timestampFiltrelenen veriler whereTimezone değişikliklerine uygun olmadığı için yeni bir soruna neden olacağını düşünüyorum .
Erlang P

@ErlangP Bu durumda, uygulamanız datesorguyu göndermeden önce saat dilimi sorununu sütunda düzeltmelidir .
Accountant م

7

Ben her şeyi ortak bir ham biçimde tutmak ve verileri PHP kodunda veya SQL sorgunuzda formatlamak için zaman damgası kullanmayı tercih ederim. Her şeyi düz saniyeler içinde tutmak için kodunuzda kullanışlı olduğu durumlar vardır.



6

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);

4
Ya da, insan tarafından okunabilir ve yerel bir MySQL tarih saatini kullanın ve tarihler eklemek / alt tarihler eklemek için yerel MySQL işlevlerini kullanın.
Julien Palard
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.