8.3.14 Indexed Lookups from TIMESTAMP Columns从TIMESTAMP列进行索引查找

Temporal values are stored in TIMESTAMP columns as UTC values, and values inserted into and retrieved from TIMESTAMP columns are converted between the session time zone and UTC. 时间值作为UTC值存储在TIMESTAMP列中,插入时间戳列和从时间戳列检索的值在会话时区和UTC之间转换。(This is the same type of conversion performed by the CONVERT_TZ() function. (这与CONVERT_TZ()函数执行的转换类型相同。If the session time zone is UTC, there is effectively no time zone conversion.)如果会话时区为UTC,则实际上没有时区转换。)

Due to conventions for local time zone changes such as Daylight Saving Time (DST), conversions between UTC and non-UTC time zones are not one-to-one in both directions. 由于夏令时(DST)等本地时区更改的约定,UTC和非UTC时区之间的转换不是双向的一对一。UTC values that are distinct may not be distinct in another time zone. 不同的UTC值在其他时区中可能不不同。The following example shows distinct UTC values that become identical in a non-UTC time zone:以下示例显示在非UTC时区中变得相同的不同UTC值:

mysql> CREATE TABLE tstable (ts TIMESTAMP);
mysql> SET time_zone = 'UTC'; -- insert UTC values
mysql> INSERT INTO tstable VALUES
('2018-10-28 00:30:00'),
('2018-10-28 01:30:00');
mysql> SELECT ts FROM tstable;
+---------------------+
| ts                  |
+---------------------+
| 2018-10-28 00:30:00 |
| 2018-10-28 01:30:00 |
+---------------------+
mysql> SET time_zone = 'MET'; -- retrieve non-UTC values
mysql> SELECT ts FROM tstable;
+---------------------+
| ts                  |
+---------------------+
| 2018-10-28 02:30:00 |
| 2018-10-28 02:30:00 |
+---------------------+
Note注意

To use named time zones such as 'MET' or 'Europe/Amsterdam', the time zone tables must be properly set up. 要使用命名时区,如'MET''Europe/Amsterdam',必须正确设置时区表。For instructions, see Section 5.1.15, “MySQL Server Time Zone Support”.有关说明,请参阅第5.1.15节,“MySQL服务器时区支持”

You can see that the two distinct UTC values are the same when converted to the 'MET' time zone. 您可以看到,两个不同的UTC值在转换为'MET'时区时是相同的。This phenomenon can lead to different results for a given TIMESTAMP column query, depending on whether the optimizer uses an index to execute the query.这种现象可能会导致给定TIMESTAMP列查询的不同结果,这取决于优化器是否使用索引执行查询。

Suppose that a query selects values from the table shown earlier using a WHERE clause to search the ts column for a single specific value such as a user-provided timestamp literal:假设查询使用WHERE子句从前面显示的表中选择值,以在ts列中搜索单个特定值,例如用户提供的时间戳文字:

SELECT ts FROM tstable
WHERE ts = 'literal';

Suppose further that the query executes under these conditions:进一步假设查询在以下条件下执行:

Under those conditions, the comparison in the WHERE clause occurs in different ways for nonindexed and indexed lookups and leads to different results:在这些条件下,WHERE子句中的比较以不同的方式进行非索引和索引查找,并导致不同的结果:

Due to different optimizer operation for nonindexed and indexed lookups, the query produces different results in each case. 由于优化器对非索引和索引查找的操作不同,查询在每种情况下都会产生不同的结果。The result from the nonindexed lookup returns all values that match in the session time zone. 非索引查找的结果返回会话时区中匹配的所有值。The indexed lookup cannot do so:索引查找无法执行此操作:

In the preceding discussion, the data set stored in tstable happens to consist of distinct UTC values. 在前面的讨论中,tstable中存储的数据集恰好由不同的UTC值组成。In such cases, all index-using queries of the form shown match at most one index entry.在这种情况下,所有使用所示形式的查询的索引最多匹配一个索引项。

If the index is not UNIQUE, it is possible for the table (and the index) to store multiple instances of a given UTC value. 如果索引不是UNIQUE,则表(和索引)可以存储给定UTC值的多个实例。For example, the ts column might contain multiple instances of the UTC value '2018-10-28 00:30:00'. 例如,ts列可能包含UTC值'2018-10-28 00:30:00'的多个实例。In this case, the index-using query would return each of them (converted to the MET value '2018-10-28 02:30:00' in the result set). 在这种情况下,使用查询的索引将返回它们中的每一个(转换为结果集中的MET值'2018-10-28 02:30:00')。It remains true that index-using queries match the converted search value to a single value in the UTC index entries, rather than matching multiple UTC values that convert to the search value in the session time zone.确实,使用查询的索引将转换的搜索值与UTC索引项中的单个值相匹配,而不是与转换为会话时区中搜索值的多个UTC值相匹配。

If it is important to return all ts values that match in the session time zone, the workaround is to suppress use of the index with an IGNORE INDEX hint:如果返回会话时区中匹配的所有ts值很重要,变通方法是使用IGNORE INDEX提示来禁止使用索引:

mysql> SELECT ts FROM tstable
IGNORE INDEX (ts)
WHERE ts = '2018-10-28 02:30:00';
+---------------------+
| ts                  |
+---------------------+
| 2018-10-28 02:30:00 |
| 2018-10-28 02:30:00 |
+---------------------+

The same lack of one-to-one mapping for time zone conversions in both directions occurs in other contexts as well, such as conversions performed with the FROM_UNIXTIME() and UNIX_TIMESTAMP() functions. 在其他上下文中,如使用FROM_UNIXTIME()UNIX_TIMESTAMP()函数执行的转换,在两个方向上的时区转换同样缺乏一对一的映射。See Section 12.7, “Date and Time Functions”.请参阅第12.7节,“日期和时间功能”