SlideShare a Scribd company logo
Software Developer
MySQL Optimizer team
January, 2020
Martin Hansson
How to avoid the most common pitfalls of date and time types in MySQL
Everything you always wanted to know about
datetime types but didn’t have time to ask
The following is intended to outline our general product direction. It is intended for information purposes only, and
may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality,
and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of
any features or functionality described for Oracle’s products may change and remains at the sole discretion of
Oracle Corporation.
Safe harbor statement
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted2
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted3
Software Engineer
OptimizerTeam
Oracle
Martin Hansson
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted4
5
4
3
2
1
Stick with ISO formats
Don’t use invalid dates
Prefer NULL over zero dates
Use UTC as time zone on servers
When in doubt, choose DATETIME over TIMESTAMP
Take-home points
The Main Players
TIMESTAMP
Format
Limits
Time
Zone
32-bit seconds since Epoch (time_t)
1970-01-01 00:00:01 UTC to
2038-01-19 04:14:07 UTC
Session time zone in server, UTC in SE
DATETIME
Bit-encoded year, month, day, etc, 5 bytes.
1000-01-01 00:00:00 to
9999-12-31 23:59:59
None
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted6
The Daylight Saving Problem
CET
00:00
00:30
01:00
01:30
03:00
03:30
04:00
04:30
23:00
23:30
00:00
00:30
01:00
01:30
02:00
02:30
UTC
Adjusting to SummerTime
CET
01:00
01:30
02:00
02:30
02:00
02:30
03:00
03:30
23:00
23:30
00:00
00:30
01:00
01:30
02:00
02:30
UTC
Adjusting to WinterTime
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted9
mysql> SELECT from_unixtime(1572136200) AS tG
*************************** 1. row ***************************
t: 2019-10-27 02:30:00
1 row in set (0.02 sec)
MySQL Chooses the Later time
mysql> SELECT unix_timestamp('2019-10-27 02:30:00') AS tG
*************************** 1. row ***************************
t: 1572139800
1 row in set (0.01 sec)
mysql> SELECT from_unixtime(1572139800) AS tG
*************************** 1. row ***************************
t: 2019-10-27 02:30:00
1 row in set (0.02 sec)
= 0:30 UTC
= 1:30 UTC
= 1:30 UTC
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted10
mysql> SET time_zone= 'UTC';
mysql> CREATE TABLE t( a TIMESTAMP );
mysql> INSERT INTO t VALUES
-> ( '2019-10-27 00:30' ),
-> ( '2019-10-27 00:59' ),
-> ( '2019-10-27 01:00' );
Ordering
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted11
Ordering
mysql> SET time_zone = 'CET';
mysql> SELECT * FROM t ORDER BY a;
+---------------------+
| a |
+---------------------+
| 2019-10-27 02:30:00 |
| 2019-10-27 02:59:00 |
| 2019-10-27 02:00:00 |
+---------------------+
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted12
Ordering
mysql> SET time_zone = 'CET';
mysql> SELECT * FROM t ORDER BY a;
+---------------------+
| a |
+---------------------+
| 2019-10-27 02:30:00 |
| 2019-10-27 02:59:00 |
| 2019-10-27 02:00:00 |
+---------------------+
MySQL Architecture
Indexes
Tables
Comparison Operators
Filesort
SQL layer
Storage
Engine
Layer
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted14
• Strictly ±hh:mm
• -14:00 to +14:00
• Only with ISO8601 Extended Format:
• YYYY-MM-DD␣hh:mm:ss±hh:mm
• YYYY-MM-DDThh:mm:ss±hh:mm
• Only valid dates.
Store the Time You Want
New since 8.0.19
2020-01-27 10:25:39+01:00
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted15
Client/Server protocol
Store the Time You Want
New since 8.0.19
Length Year Month Day Hour Minute Second Fractional
Second
Time
Zone
1 2 1 1 1 1 1 4 2
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted16
mysql> INSERT INTO times VALUES ( '2019-10-27 00:30:00+00:00' );
Query OK, 1 row affected (0.02 sec)
mysql> SELECT * FROM times;
+---------------------+
| time_stamp |
+---------------------+
| 2019-10-27 02:30:00 |
+---------------------+
1 row in set (0.00 sec)
Store the Time You Want
New since 8.0.19
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted17
mysql> INSERT INTO times VALUES ( '2019-10-27 00:30:00+00:00' );
Query OK, 1 row affected (0.02 sec)
mysql> SELECT /*+ SET_VAR(time_zone = UTC) */ * FROM times;
+---------------------+
| time_stamp |
+---------------------+
| 2019-10-27 00:30:00 |
+---------------------+
1 row in set (0.00 sec)
Read What’s Stored
New since 8.0.17
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted18
5
4
3
2
1
Stick with ISO formats
Don’t use invalid dates
Prefer NULL over zero dates
Use UTC as server time zone
When in doubt, use DATETIME over TIMESTAMP
Take-home points
SQL Standard
DATE
TIME WITHOUT TIME ZONE
TIME WITH TIME ZONE
TIMESTAMP WITHOUT TIME ZONE
TIMESTAMP WITH TIME ZONE
DATE
TIME
DATETIME
TIMESTAMP
MySQL
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted20
5
4
3
2
1
Stick with ISO formats
Don’t use invalid dates
Prefer NULL over zero dates
Use UTC as server time zone
When in doubt, use DATETIME over TIMESTAMP
Take-home points
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted21
5
4
3
2
1
Stick with ISO formats
Don’t use invalid dates
Prefer NULL over zero dates
Use UTC as server time zone
When in doubt, use DATETIME over TIMESTAMP
Take-home points
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted22
0000-00-00 00:00:00
The Zero Date
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted23
• Automatic initialization
• Easier
• Less space
• Efficiency
• Legacy
Why use it?
Zero Dates
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted24
What is it?
Automatic Initialization of Dates
CREATE TABLE member (
…
signup_time TIMESTAMP DEFAULT NOW()
);
CREATE TABLE member (
…
last_updated TIMESTAMP ON UPDATE NOW()
);
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted25
Old since MySQL 5.6.5
Automatic Initialization of Dates
CREATE TABLE member (
id INT PRIMARY KEY,
joined DATETIME DEFAULT NOW(),
really_joined DATETIME DEFAULT NOW(),
last_updated DATETIME ON UPDATE NOW()
);
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted26
• Automatic initialization
• Easier
• Less space
• Efficiency
• Legacy
Why use it?
Zero Dates
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted27
What is it?
Three-valued Logic isYour Friend
SELECT * FROM member WHERE signup_time IS UNKNOWN;
SELECT * FROM member WHERE last_update IS UNKNOWN;
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted28
What is it?
Three-valued Logic isYour Friend
SELECT signup_time FROM member WHERE signup_time <
‘2018-10-01’;
+---------------------+
| signup_time |
+---------------------+
| 2018-09-10 11:07:51 |
| … |
+---------------------+
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted29
What is it?
Three-valued Logic isYour Friend
SELECT signup_time FROM member WHERE signup_time <
‘2018-10-01’;
+---------------------+
| signup_time |
+---------------------+
| 0000-00-00 00:00:00 |
| … |
+---------------------+
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted30
• Automatic initialization
• Easier
• Less space
• Efficiency
• Legacy
Why use it?
Zero Dates
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted31
• Automatic initialization
• Easier
• Less space
• Efficiency
• Legacy
Why use it?
Zero Dates
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted32
• Automatic initialization
• Easier
• Less space
• Efficiency
• Legacy
Why use it?
Zero Dates
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted33
5
4
3
2
1
Stick with ISO formats
Don’t use invalid dates
Prefer NULL over zero dates
Use UTC as server time zone
When in doubt, use DATETIME over TIMESTAMP
Take-home points
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted34
5
4
3
2
1
Stick with ISO formats
Don’t use invalid dates
Prefer NULL over zero dates
Use UTC as server time zone
When in doubt, use DATETIME over TIMESTAMP
Take-home points
Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted35
Truncated
Removed in ISO8601:2004
Basic
Extended 2020-01-30T10:00:00, 2020-01-30T10:00
The ISO8601 Standard
20200130100000
20200130T100000
200130100000
RFC3339 2020-01-30 10:00:00, 2020-01-30 10:00
ThankYou
Questions?
Martin Hansson

More Related Content

Similar to Everything you always wanted to know about datetime types but didn’t have time to ask (20)

PDF
MySQL Cookbook 1st ed Edition Paul Dubois
uzielklael28
 
PDF
PHPDay 2019 - MySQL 8, not only good, great!
Gabriela Ferrara
 
PPT
Teradata 13.10
Teradata
 
PPT
e computer notes - Date time functions
ecomputernotes
 
PDF
Temporal Data
Command Prompt., Inc
 
PPTX
Date rangestech15
stewashton
 
PPT
Toc Sg
Sudharsan S
 
PPTX
Oracle 12c SQL: Date Ranges
Stew Ashton
 
PDF
Database Design most common pitfalls
Federico Razzoli
 
PPTX
What's new in MariaDB TX 3.0
MariaDB plc
 
PDF
Temporal Databases: Queries
torp42
 
PPTX
MYSQL DATA TYPES for newbies helpful.pptx
Farhat991731
 
PDF
Comprehensive View on Date-time APIs of Apache Spark 3.0
Databricks
 
PDF
What’s New in MariaDB TX 3.0
MariaDB plc
 
PDF
What's new in MariaDB TX 3.0
MariaDB plc
 
PDF
Laracon EU 2018: OMG MySQL 8.0 is out! are we there yet?
Gabriela Ferrara
 
DOC
Timewizard Public
Praveen Kumar Peddi
 
DOC
Date Time Article
Praveen Kumar Peddi
 
PPTX
Date and time functions in mysql
V.V.Vanniaperumal College for Women
 
PDF
SQL Outer Joins for Fun and Profit
Karwin Software Solutions LLC
 
MySQL Cookbook 1st ed Edition Paul Dubois
uzielklael28
 
PHPDay 2019 - MySQL 8, not only good, great!
Gabriela Ferrara
 
Teradata 13.10
Teradata
 
e computer notes - Date time functions
ecomputernotes
 
Temporal Data
Command Prompt., Inc
 
Date rangestech15
stewashton
 
Toc Sg
Sudharsan S
 
Oracle 12c SQL: Date Ranges
Stew Ashton
 
Database Design most common pitfalls
Federico Razzoli
 
What's new in MariaDB TX 3.0
MariaDB plc
 
Temporal Databases: Queries
torp42
 
MYSQL DATA TYPES for newbies helpful.pptx
Farhat991731
 
Comprehensive View on Date-time APIs of Apache Spark 3.0
Databricks
 
What’s New in MariaDB TX 3.0
MariaDB plc
 
What's new in MariaDB TX 3.0
MariaDB plc
 
Laracon EU 2018: OMG MySQL 8.0 is out! are we there yet?
Gabriela Ferrara
 
Timewizard Public
Praveen Kumar Peddi
 
Date Time Article
Praveen Kumar Peddi
 
Date and time functions in mysql
V.V.Vanniaperumal College for Women
 
SQL Outer Joins for Fun and Profit
Karwin Software Solutions LLC
 

Recently uploaded (20)

PDF
How to Connect Your On-Premises Site to AWS Using Site-to-Site VPN.pdf
Tamanna
 
PPTX
apidays Munich 2025 - Building Telco-Aware Apps with Open Gateway APIs, Subhr...
apidays
 
PDF
Product Management in HealthTech (Case Studies from SnappDoctor)
Hamed Shams
 
PPTX
ER_Model_with_Diagrams_Presentation.pptx
dharaadhvaryu1992
 
PDF
Data Chunking Strategies for RAG in 2025.pdf
Tamanna
 
PDF
apidays Helsinki & North 2025 - Monetizing AI APIs: The New API Economy, Alla...
apidays
 
PDF
JavaScript - Good or Bad? Tips for Google Tag Manager
📊 Markus Baersch
 
PPTX
ER_Model_Relationship_in_DBMS_Presentation.pptx
dharaadhvaryu1992
 
PDF
apidays Helsinki & North 2025 - REST in Peace? Hunting the Dominant Design fo...
apidays
 
PPTX
apidays Helsinki & North 2025 - APIs at Scale: Designing for Alignment, Trust...
apidays
 
PPTX
apidays Singapore 2025 - From Data to Insights: Building AI-Powered Data APIs...
apidays
 
PPTX
apidays Helsinki & North 2025 - API access control strategies beyond JWT bear...
apidays
 
PDF
Choosing the Right Database for Indexing.pdf
Tamanna
 
PPTX
apidays Munich 2025 - Building an AWS Serverless Application with Terraform, ...
apidays
 
PDF
apidays Helsinki & North 2025 - APIs in the healthcare sector: hospitals inte...
apidays
 
PDF
The European Business Wallet: Why It Matters and How It Powers the EUDI Ecosy...
Lal Chandran
 
PDF
Building Production-Ready AI Agents with LangGraph.pdf
Tamanna
 
PPTX
apidays Singapore 2025 - The Quest for the Greenest LLM , Jean Philippe Ehre...
apidays
 
PDF
What does good look like - CRAP Brighton 8 July 2025
Jan Kierzyk
 
PPTX
Exploring Multilingual Embeddings for Italian Semantic Search: A Pretrained a...
Sease
 
How to Connect Your On-Premises Site to AWS Using Site-to-Site VPN.pdf
Tamanna
 
apidays Munich 2025 - Building Telco-Aware Apps with Open Gateway APIs, Subhr...
apidays
 
Product Management in HealthTech (Case Studies from SnappDoctor)
Hamed Shams
 
ER_Model_with_Diagrams_Presentation.pptx
dharaadhvaryu1992
 
Data Chunking Strategies for RAG in 2025.pdf
Tamanna
 
apidays Helsinki & North 2025 - Monetizing AI APIs: The New API Economy, Alla...
apidays
 
JavaScript - Good or Bad? Tips for Google Tag Manager
📊 Markus Baersch
 
ER_Model_Relationship_in_DBMS_Presentation.pptx
dharaadhvaryu1992
 
apidays Helsinki & North 2025 - REST in Peace? Hunting the Dominant Design fo...
apidays
 
apidays Helsinki & North 2025 - APIs at Scale: Designing for Alignment, Trust...
apidays
 
apidays Singapore 2025 - From Data to Insights: Building AI-Powered Data APIs...
apidays
 
apidays Helsinki & North 2025 - API access control strategies beyond JWT bear...
apidays
 
Choosing the Right Database for Indexing.pdf
Tamanna
 
apidays Munich 2025 - Building an AWS Serverless Application with Terraform, ...
apidays
 
apidays Helsinki & North 2025 - APIs in the healthcare sector: hospitals inte...
apidays
 
The European Business Wallet: Why It Matters and How It Powers the EUDI Ecosy...
Lal Chandran
 
Building Production-Ready AI Agents with LangGraph.pdf
Tamanna
 
apidays Singapore 2025 - The Quest for the Greenest LLM , Jean Philippe Ehre...
apidays
 
What does good look like - CRAP Brighton 8 July 2025
Jan Kierzyk
 
Exploring Multilingual Embeddings for Italian Semantic Search: A Pretrained a...
Sease
 
Ad

Everything you always wanted to know about datetime types but didn’t have time to ask

  • 1. Software Developer MySQL Optimizer team January, 2020 Martin Hansson How to avoid the most common pitfalls of date and time types in MySQL Everything you always wanted to know about datetime types but didn’t have time to ask
  • 2. The following is intended to outline our general product direction. It is intended for information purposes only, and may not be incorporated into any contract. It is not a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. The development, release, timing, and pricing of any features or functionality described for Oracle’s products may change and remains at the sole discretion of Oracle Corporation. Safe harbor statement Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted2
  • 3. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted3 Software Engineer OptimizerTeam Oracle Martin Hansson
  • 4. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted4 5 4 3 2 1 Stick with ISO formats Don’t use invalid dates Prefer NULL over zero dates Use UTC as time zone on servers When in doubt, choose DATETIME over TIMESTAMP Take-home points
  • 5. The Main Players TIMESTAMP Format Limits Time Zone 32-bit seconds since Epoch (time_t) 1970-01-01 00:00:01 UTC to 2038-01-19 04:14:07 UTC Session time zone in server, UTC in SE DATETIME Bit-encoded year, month, day, etc, 5 bytes. 1000-01-01 00:00:00 to 9999-12-31 23:59:59 None
  • 6. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted6 The Daylight Saving Problem
  • 9. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted9 mysql> SELECT from_unixtime(1572136200) AS tG *************************** 1. row *************************** t: 2019-10-27 02:30:00 1 row in set (0.02 sec) MySQL Chooses the Later time mysql> SELECT unix_timestamp('2019-10-27 02:30:00') AS tG *************************** 1. row *************************** t: 1572139800 1 row in set (0.01 sec) mysql> SELECT from_unixtime(1572139800) AS tG *************************** 1. row *************************** t: 2019-10-27 02:30:00 1 row in set (0.02 sec) = 0:30 UTC = 1:30 UTC = 1:30 UTC
  • 10. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted10 mysql> SET time_zone= 'UTC'; mysql> CREATE TABLE t( a TIMESTAMP ); mysql> INSERT INTO t VALUES -> ( '2019-10-27 00:30' ), -> ( '2019-10-27 00:59' ), -> ( '2019-10-27 01:00' ); Ordering
  • 11. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted11 Ordering mysql> SET time_zone = 'CET'; mysql> SELECT * FROM t ORDER BY a; +---------------------+ | a | +---------------------+ | 2019-10-27 02:30:00 | | 2019-10-27 02:59:00 | | 2019-10-27 02:00:00 | +---------------------+
  • 12. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted12 Ordering mysql> SET time_zone = 'CET'; mysql> SELECT * FROM t ORDER BY a; +---------------------+ | a | +---------------------+ | 2019-10-27 02:30:00 | | 2019-10-27 02:59:00 | | 2019-10-27 02:00:00 | +---------------------+
  • 14. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted14 • Strictly ±hh:mm • -14:00 to +14:00 • Only with ISO8601 Extended Format: • YYYY-MM-DD␣hh:mm:ss±hh:mm • YYYY-MM-DDThh:mm:ss±hh:mm • Only valid dates. Store the Time You Want New since 8.0.19 2020-01-27 10:25:39+01:00
  • 15. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted15 Client/Server protocol Store the Time You Want New since 8.0.19 Length Year Month Day Hour Minute Second Fractional Second Time Zone 1 2 1 1 1 1 1 4 2
  • 16. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted16 mysql> INSERT INTO times VALUES ( '2019-10-27 00:30:00+00:00' ); Query OK, 1 row affected (0.02 sec) mysql> SELECT * FROM times; +---------------------+ | time_stamp | +---------------------+ | 2019-10-27 02:30:00 | +---------------------+ 1 row in set (0.00 sec) Store the Time You Want New since 8.0.19
  • 17. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted17 mysql> INSERT INTO times VALUES ( '2019-10-27 00:30:00+00:00' ); Query OK, 1 row affected (0.02 sec) mysql> SELECT /*+ SET_VAR(time_zone = UTC) */ * FROM times; +---------------------+ | time_stamp | +---------------------+ | 2019-10-27 00:30:00 | +---------------------+ 1 row in set (0.00 sec) Read What’s Stored New since 8.0.17
  • 18. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted18 5 4 3 2 1 Stick with ISO formats Don’t use invalid dates Prefer NULL over zero dates Use UTC as server time zone When in doubt, use DATETIME over TIMESTAMP Take-home points
  • 19. SQL Standard DATE TIME WITHOUT TIME ZONE TIME WITH TIME ZONE TIMESTAMP WITHOUT TIME ZONE TIMESTAMP WITH TIME ZONE DATE TIME DATETIME TIMESTAMP MySQL
  • 20. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted20 5 4 3 2 1 Stick with ISO formats Don’t use invalid dates Prefer NULL over zero dates Use UTC as server time zone When in doubt, use DATETIME over TIMESTAMP Take-home points
  • 21. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted21 5 4 3 2 1 Stick with ISO formats Don’t use invalid dates Prefer NULL over zero dates Use UTC as server time zone When in doubt, use DATETIME over TIMESTAMP Take-home points
  • 22. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted22 0000-00-00 00:00:00 The Zero Date
  • 23. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted23 • Automatic initialization • Easier • Less space • Efficiency • Legacy Why use it? Zero Dates
  • 24. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted24 What is it? Automatic Initialization of Dates CREATE TABLE member ( … signup_time TIMESTAMP DEFAULT NOW() ); CREATE TABLE member ( … last_updated TIMESTAMP ON UPDATE NOW() );
  • 25. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted25 Old since MySQL 5.6.5 Automatic Initialization of Dates CREATE TABLE member ( id INT PRIMARY KEY, joined DATETIME DEFAULT NOW(), really_joined DATETIME DEFAULT NOW(), last_updated DATETIME ON UPDATE NOW() );
  • 26. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted26 • Automatic initialization • Easier • Less space • Efficiency • Legacy Why use it? Zero Dates
  • 27. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted27 What is it? Three-valued Logic isYour Friend SELECT * FROM member WHERE signup_time IS UNKNOWN; SELECT * FROM member WHERE last_update IS UNKNOWN;
  • 28. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted28 What is it? Three-valued Logic isYour Friend SELECT signup_time FROM member WHERE signup_time < ‘2018-10-01’; +---------------------+ | signup_time | +---------------------+ | 2018-09-10 11:07:51 | | … | +---------------------+
  • 29. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted29 What is it? Three-valued Logic isYour Friend SELECT signup_time FROM member WHERE signup_time < ‘2018-10-01’; +---------------------+ | signup_time | +---------------------+ | 0000-00-00 00:00:00 | | … | +---------------------+
  • 30. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted30 • Automatic initialization • Easier • Less space • Efficiency • Legacy Why use it? Zero Dates
  • 31. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted31 • Automatic initialization • Easier • Less space • Efficiency • Legacy Why use it? Zero Dates
  • 32. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted32 • Automatic initialization • Easier • Less space • Efficiency • Legacy Why use it? Zero Dates
  • 33. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted33 5 4 3 2 1 Stick with ISO formats Don’t use invalid dates Prefer NULL over zero dates Use UTC as server time zone When in doubt, use DATETIME over TIMESTAMP Take-home points
  • 34. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted34 5 4 3 2 1 Stick with ISO formats Don’t use invalid dates Prefer NULL over zero dates Use UTC as server time zone When in doubt, use DATETIME over TIMESTAMP Take-home points
  • 35. Copyright © 2020, Oracle and/or its affiliates | Confidential: Internal/Restricted/Highly Restricted35 Truncated Removed in ISO8601:2004 Basic Extended 2020-01-30T10:00:00, 2020-01-30T10:00 The ISO8601 Standard 20200130100000 20200130T100000 200130100000 RFC3339 2020-01-30 10:00:00, 2020-01-30 10:00

Editor's Notes

  • #2: Should maybe be temporal types
  • #4: I’m a code monkey in the mysql optimizer team who turned a teenager last year. Feels good to call myself that. Been working with mysql for 13 years now. The last few years I’ve been wallowing around in the boondocks of the optimizer with regular expressions, character sets and now time zones. All the fun stuff.
  • #5: Right off the bat/ Here are the points I like you to take with you. (read) If you follow all of these, I will be happy. And you will be happy, too. I hope that I can convince you to follow these.
  • #6: These are the most important temporal types. We have the types date and time as well but they are not as commonly used These types can also have 1-6 fractional digits, but it works the same way in all types. I’ts one, two or three bytes. But this for comparison. A timestamp is a Unix time_t underneath unless you have fractional digits. Note that on disk, it’s a 32 bit time_t. A datetime is all the numbers packed together. Sign + 17 (year+month), 5 bits day hour, 6 bits minute second. 40 bits. 5 Bytes TIMESTAMP has the same limitation as time_t and it has the infamous year 2038 problem (more precisely…) when it wraps around. DATETIME runs from 1000 to 9999. Let’s just say it’s slightly more future proof. Supports some invalid dates, zero day or month, leap day etc. Not that you should do that. Understand there’s a lot of legacy out there. And then there’s the thing with time zone. A datetime is what it is. Whatever you store you get back, regardless. A timestamp is converted from the session’s time zone and stored as utc. When read it’s converted back to your time zone. If that time zone observes daylight saving, we have a problem.
  • #7: 5 min. This problem is so big it gets its own slide. Let me talk a bit about what I call the ds problem. There’s a lot of things that can go wrong when you query data stored as TIMESTAMP and ds comes into play. - Some rows may be equal under certain conditions, different in others. - Ordering of rows may be unexpected - Replication slaves may go out of sync, creating problems for analytics - Queries over unique indexes may appear to produce duplicates All of these boil down to the daylight savings problem. What is that? Many countries use daylight savings. It means that in summer time, clocks are set ahead one hour so that people have one extra hour of daylight after work. In fall, the clocks are set back one hour. So we have one 23 hour day in spring, and a 25 hour day in fall. The idea of daylight saving was proposed by the astronomer George Hudson in 1895 and was in use for the first time in 1917 in the German empire, and it’s controversial to this day. The main proponents were golfers and entomologists who didn’t like to cut their activities short at dusk. For some time they experimented with having government meetings eariler in the day in summer, but eventually they settled for simply setting the clocks forward. It’s really unique for a unit of measurement to be tailored to a specific purpose. I wish we’d do the same with other units. Maybe make a kilo heavier around Christmas time? In the Nordic countries, wher I live, we don’t care about daylight saing so much because in the summer you have as much daylight as you can take either way. The sun is up when I wake up, and it’s still up when I go to bed. And in the winter, who cares? It’s pitch black when I go to work and pitch black when I get home.
  • #8: UTC time doesn’t observe daylight savings. So in a time zone that has dst, the displacement from UTC time will vary. This happened on Sunday March 31 last year. Instead of going from 1:59 to 2, the clock jumped from 1:59 to 3, thereby moving the displacement from utc. Skipping ahead to be two hours ahead of UTC. This means that there is a whole hour that doesn’t exist in the cet calendar. A leap hour if you wish. But it doesn’t get much worse than that. The shift in the other direction is far worse.
  • #9: On October 27 last year at 3 in the morning, this happened. After 2:59:59, the next second it was 2 am yet again, and the displacement from UTC became not two but just one hour. So in the CET time zone we’re reliving one hour each fall, groundhog day-style. This is a very popular hours to go partying where I live because the authorities force the bars to close at 3. So at 2:59 you have another hour to party! As you can see, the conversion from UTC to CET is not lossless. <tryck> If you only see 2:30, it could mean two different times. <tryck> MySQL will always choose the later interpretation in these cases.
  • #10: Here’s a demonstration where mysql chooses the later time. The big number is the time_t value, or seconds since the unix epoch January first 1970. <Tryck fram> The numbers are 3600 seconds apart, which is 60 x 60, one hour. Which is the groundhog hour. And when it gets an ambiguous time such as 2:30, <tryck fram> it chooses the later time. The representation is different on different levels, which has some surprising effects! Let me show you what I mean by that with an example.
  • #11: Let me show you where ordering goes awry. We first set the time zone to utc and insert times right in the groundhog hour. <read>
  • #12: 10 min. All is well. Now let’s just change the time zone back to CET and let’s get the rows. And let’s get them in order, please.
  • #13: Waat? As we change the time zone to CET, the times look funny. there’s 59 min from the second to the third. And ordering?! Is MySQL trolling us? Actually it isn’t, because these times are stored as 0:30, 0:59 and 1:00 am. We only interpret the output of filesort in our local time zone. We would get the same result event with an index. We’ll need to take a look at mysql’s architecture to sort this out.
  • #14: In the storage engine layer is where the tables and indexes live. Here timestamps are utc. In the sql layer we have the time in our local time zone, mostly. As you saw in the previous slide, I had to play with the time_zone variable to deliver these examples. I don’t know bout you but I find it annoying having to change the time zone around all the time. Beside, that’s not really an option for some of you. The application might not let you, or you reuse your sessions.
  • #15: Since 8.0.19, you can add a tz to a ts or dt literal. Expressed as displacement from UTC. That looks like a plus or minus sign, with hours and minutes, two digits each. Note that we follow ISO8601 to the letter here. Mysql is extremely liberal with the syntax of temporal literals, and this is a complete departure from that. The range is -14 to +14 as the sql standard prescribes, it used to be 13, so we bumped it up for that very reason. You can ONLY use it only with the ISO8601 extended format, which looks exactly as these. Only valid dates: internally dates are converted to the equivalent of epoch seconds, then displacement subtracted, then converted back. An invalid date has an undefined result when you convert to epoch seconds.
  • #16: 15 min. You can of course use it in the client/server protocol as well. It is then an extra signed 2-byte integer for the time zone. Added to the MYSQL_TIME struct. So now we have 4 bytes for date values, 7 for date+time, 11 for date+time w/fractional, and 13 byte value for date+time+fractional+tz. We deliberately didn’t do a 9 byte value for date+time+tz b/c didn’t want to paint ourselves into a corner. In case we want to extend this in the future.
  • #17: Armed with this, what happens when you use a displacement of zero to insert into a TIMESTAMP column is you insert exactly what you see. What you see is what you get. Now, as you can see, the client is still on CET, which does the lossy conversion from UTC. to 2:30. Ambigous. Say I want to see it in UTC. Let’s fix that.
  • #18: Since 8.017, you can use the set_var hint in comment hints. That way you can temporarily a session var to something else for the duration of a statement. Works for select, insert, update, delete. It looks like this. No quotes So if we set it to utc, we’re going to get back what we stored, lossless.
  • #19: So, as you can see, TIMESTAMP is challenging to work with. DATETIME has none of these drawbacks. Granted, it doesn’t have a time zone information so the application has to convert it. Convention. Another reason we push for datetime is standard.
  • #20: The SQL standard define three temporal types: date, time and timestamp. Timestamp and time come with or w/o tz. Temporal values w/o tz don’t point to a specific point in time, they need to be interpreted through a tz. time w/tz is a specific time but not a specific date. ts w/tz points to an exact time no matter the tz of the client that inserted it. There is no loss of info here. We have four types Date and time act like standard. DATETIME most similar to ts w/o tz. Timestamp is an odd creature in this regard. somewhere in between the two. It’s a tswtz in the storage engine, but only UTC. And it’s displayed as tswotz to the user. where all the problems stem from.
  • #21: Hopefully It’s obvious by now why it’s a good idea to have the database server set to utc. Either the entire box, or set globally in Mysql server.
  • #22: Why should you use NULL instead of zero dates? What is it even? <ask>
  • #23: So without further ado, I present to you, the zero date. This is what it looks like. Obviously, just a hack that was needed at some point. So why shouldn’t you use it?
  • #24: I’ll turn the question around. My question is, why would you? These are some of the arguments in favor of “zero dates” – or myths, I should call them. Let’s debunk them. We start with automatic init
  • #25: This is automatic initialization of dates. You can have a row auto updated either when the row is inserted or when it’s updated. In the past there were a weird set of restrictions. The column had to be TIMESTAMP, it had to be NOT NULL, and it had to be the first such column. You couldn’t have one column default now() and one on update now(). for example. This forced users to resort to the zero date hack when they needed a null value. There is also some support for it in the server. That’s why the lowest timestamp is jan first 1970 at midnight PLUS ONE SECOND because the zero value is reserved to mean “zero date”.
  • #26: 20 min. BUT the previous slide hasn’t been true since 5.6.5. Nowadays you can have auto init for datetime and as many as you like. Mix and match. Knock yourself out. and yes they can have null in them.
  • #27: Is it easier? The relational model was made for this.
  • #28: Easier. How can It possible be any easier than that? It’s plain English. In SQL, NULL means “piece of information missing”. Some say NULL loses all comparisons. That’s not really true, the result is UNKNOWN. But the WHERE clause has an implicit IS TRUE predicate. Which you bypass easy by adding another IS UNKNOWN pred on top. If you work with the relational model, it all works out. If you don’t like the relational model, fine, you can use mysql as a document store. That’s fine, too. But this kind of hack will only make life harder.
  • #29: If you use NULL, it will get filtered out from your comparisons by default, so you only get known times.
  • #30: However, if you have the zero date, it is a valid value and a query like this will give you all zero dates unless you add a special case fo it.
  • #31: What about less space though? In fact, the opposite is true. In the Barracuda format in InnoDB we have null bytes before each record, so typically a null value doesn’t take up any space at all. [todo mer detaljer]
  • #32: Efficiency? Nah, comparison with null takes exactly the same time as comparison with the zero date. There’s a statistically insignificant slant in *favor* of NULLs. This holds for both myisam and innodb, btw.
  • #33: A very valid reason to use zero dates is because of legacy data, which is why it’s still supported and will continue to be. But you need to be aware of the problems involved.
  • #34: Invalid dates are a headache to work with so you’re better off not letting them into your database. Arithmetic on invalid dates does not work, nor will the new time zone information. to_days(), to_seconds() give null for zero date and unexpected values for dates with zeroes. Quoting a bug report. When you do SET sql_mode = 'ALLOW_INVALID_DATES'; you cannot expect anything good after it.
  • #35: Now for my last point. ISO formats.
  • #36: We are definitely moving in the direction of following standards more and more. We have deprecated a lot of non-standard behavior in the past, like NO_ZERO_DATE, NO_ZERO_IN_DATE and ALLOW_INVALID_DATES. As I touched upon before, mysql is extremely liberal to interpret dates. And there are plenty of ways you can shoot yourself in the foot. To be on the safe side, I strongly recommend that you stick with the ISO formats. ISO8601 is most important. This standard is concerned only with the formats, not the interpretation. A general principle is that the number of digits is always fixed. There *has* to be leading zeroes in all fields. And the year *has* to have four digits. The standard uses a 24-hour clock. Sorry, all Americans. I already covered time zone so won’t go into it here. If no time zone is present, local time is assumed, which is consistent with how it works now in mysql. It comes in basically two versions, the extended and basic formats. The rfc3339 allows whitespace. There is also a truncated. y2k problem. Was removed from std in 2004. With that removed, both formats may omit the last digits for smaller precision. Always greater to smaller however.