prefer "datetime" types over "timestamp" types #54256
Open
+5
−5
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I know this has been brought up before, but I'm going to make the case again why
datetime
s are the superior data type compared totimestamp
s, and why Laravel should make these their recommended and default types for v12 and beyond.Premises
What this PR does NOT do
Parity between
datetime
andtimestamp
Storage requirements
timestamp
requires 4 bytes for storage.datetime
requires 5 bytes for storage. both allow an additional 3 bytes for precision.One of the proposals for solving the 2038 problem for
timestamp
is to increase it to a 64 bit integer, which would increase its storage requirements to 8 bytes.https://dev.mysql.com/doc/refman/8.4/en/storage-requirements.html#data-types-storage-reqs-date-time
Performance
There has been some confusion in other related PRs, Issues, and Discussions about how the performance of
datetime
would be worse thantimestamp
because it stores the date as a string, and string comparison is slower than integer comparison.datetime
is actually stored internally in a fixed length binary format which allows comparisons to be just as efficient as integer comparison.For testing, I created a table with the following migration:
I filled the table with 100,000 rows with a random date stored in both the "timestamp" and "datetime" fields. I ran the following queries and had results consistently within 1ms of each other.
Allow using "CURRENT_TIMESTAMP"
Both data types allow using the "CURRENT_TIMESTAMP" for both an initial value and an "on update" value.
datetime
benefitsSolves the 2038 issue
timestamp
fields store their value internally as a signed 32 bit integer, which means any dates after 2038/01/19 are not valid for timestamps. this is not as big of an issue right now, since most stored dates are in the past, but could potentially be a huge problem when we reach that date. it does affect current use, too, when you may be storing a future date, like an expiration.datetime
fields have a minimum value of 1000-01-01 and a maximum value of 9999-12-31, giving us a much wider valid date range, and eliminating the 2038 problemIgnorant of Server/SQL timezone
Lastly, what may be the most important of all the benefits of
datetime
, it is completely ignorant of the timezone set on either the server or SQL, whiletimestamp
is not.When a date is entered into a
timestamp
it will first attempt to convert it to UTC for internal storage. This is dependent on a couple of factors. SQL could have its own explicitly set timezone. More likely, it will be set to "SYSTEM" which means it defers to the timezone set on the OS. Either way, issues arise when SQL deems its timezone to be something other than UTC. Let's say for example, SQL's timezone is set to CST(-6). When it receives a value for a timestamp field, it will interpret the value it receives as a CST value, and convert it to UTC for internal storage, and then also convert it back to CST when the value is retrieved. Now, whether you actually intended to give it a CST value is irrelevant, because all you really care about is that the value you gave it is EXACTLY what you got back.As long as that SQL timezone value stays the same, you're actually kind of ok, even if things don't technically match up. However, things can go very poorly if the SQL timezone changes.
Imagine again we have our server with the timezone set to CST. We insert a row with a CST value, and SQL converts the
timestamp
field to UTC internally. Now someone comes along and sees that the server is set to CST, but should probably be UTC because that's pretty standard for servers. Unfortunately that simple change would mess up all of our data. Now when that row is retrieved from the database, SQL sees the server is in UTC, so it just gives the internal value it stored back to us, even though thats not correct and should have been converted.This means the value we put into the database is NOT the value we got out! Some might argue that's intentional, but I would say for the large majority of people any timezone other than UTC on the server is pure happenstance or oversight, and not actually what they intended.
If we switch to
datetime
fields, SQL ignores any server or SQL timezone settings and simply stores the value you give it, and returns exactly the same value when you request it. By making ourselves ignorant of any server settings, we actually protect ourselves from any unintentional errors like mentioned above.For some real numbers, assume we started with a server in CST, the table will show how
timestamp
anddatetime
differ.Questionable Changes
One thing I did not change was the
softDeletes()
method. I think ideally it would change to usingdatetime
s internally, and then a newsoftDeletesTimestamp()
method would be created for that specific use. However, I'm not sure how that would affect existing usage ofsoftDeletes()
that were executed when it usedtimestamp
s.