I was asking myself thses questions recently and want to share the solution I landed on for new projects.
Bigint
After reading variouse responses to questions like this one I found that storing a Unix timestamp in a Bigint column is a much better solution moving forward.
Bigints range will cover you from before the begining of time till the year 292277026596
wich may as well be called forever.
Pluss:
- It uses the same 8bytes of storage that DATETIME uses.
- Its timezone agnostic.
- You can still use auto generated timestamps via
DEFAULT (unix_timestamp())
- range is so massive your server will turn into dust before wraparounds can happen, even if storing time in miliseconds.
DECIMAL
This is the solution I landed on as you get a bit more controll.
You can store an overkill date range like bigint or reduce it to something realistic and use less storage.
In my case I also want to store frations of a second as actual fractions, and I still wanted the timestamps gerated on insert.
Heres the column definition from my create table schema:
`created` decimal(18,2) NOT NULL DEFAULT (unix_timestamp(now(2))) COMMENT 'unix timestamp'
Using decimal(18,2) provides an absolutly overkill time range with the same storage as bigint/datetime while showing fractions of a second down to 2 digits.
Storage is based on the number of digits, 9 digits = 4bytes signed or unsigned it doesnt matter.
You could limit the range to something more realistic and use significantly less than datetime or increase the precision to nanoseconds. You decide whats important.
Another advantage is, if in the distant future you hit the limit of your range, Mysql will just tell you.
No wrap around issue will happen, instead you will get an error preventing the insertion and can easily alter the table again to add another digit.
This makes for a perfect sense to me I highly recommend starting new databases with this appraoch.