mysql - 优化MYSQL查询TIMEDIFF中Select和where子句

标签 mysql query-optimization alias

我有以下在大型数据库上运行的查询。

select TIME_TO_SEC(TIMEDIFF(walkStartTime,walkEndTime)) 
from users 
where categoryType='1' 
and TIME_TO_SEC(TIMEDIFF(walkStartTime,walkEndTime)) < 1000

如果您注意到查询和 where 子句中使用了 TIME_TO_SEC。

我尝试了别名,但是由于无法使用别名,所以不知道什么是更好的解决方案。

最佳答案

我发现只有一种优化方法来查询您的问题。当您根据 WHERE 子句中的字段计算值时,MySQL 必须计算每一行。所以每次都是全表扫描,会占用很多时间,而且性能不太好。

使用计算出的时间差和索引创建一个新字段。您不必计算它,您可以使用VIRTUAL PERSISTENT字段,当您插入或更改字段时它会自动计算它

我制作了相同的示例来阐明我的想法:

首先创建一个新表:

CREATE TABLE `users` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `walkStartTime` TIMESTAMP NULL DEFAULT NULL,
  `walkEndTime` TIMESTAMP NULL DEFAULT NULL,
  `categoryType` INT(11) DEFAULT NULL,
  `diffp` INT(11) AS (TIME_TO_SEC(TIMEDIFF(walkEndTime,walkStartTime))) PERSISTENT,
  PRIMARY KEY (`id`),
  KEY `diffs` (`diffp`)
) ENGINE=INNODB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

插入一些内容:

INSERT INTO `users` (`id`, `walkStartTime`, `walkEndTime`, `categoryType`)
VALUES
    (1, '2015-09-27 07:00:00', '2015-09-27 07:30:00', 1),
    (2, '2015-09-27 07:00:01', '2015-09-27 07:31:00', 1),
    (3, '2015-09-27 07:00:02', '2015-09-27 07:32:00', 0),
    (4, '2015-09-27 07:00:10', '2015-09-27 07:15:00', 1),
    (5, '2015-09-27 07:00:20', '2015-09-27 07:16:10', 1),
    (6, '2015-09-27 07:00:30', '2015-09-27 07:17:20', 0),
    (7, '2015-09-27 07:01:00', '2015-09-27 07:10:00', 1),
    (8, '2015-09-27 07:02:00', '2015-09-27 07:09:33', 1),
    (9, '2015-09-27 07:03:00', '2015-09-27 08:12:00', 1);

尝试您的查询并解释它:看到他们读取了所有 9 行

MariaDB [tmp]> select TIME_TO_SEC(TIMEDIFF(walkEndTime,walkStartTime))
    -> from users
    -> where categoryType='1'
    -> and TIME_TO_SEC(TIMEDIFF(walkEndTime,walkStartTime)) < 1000;
+--------------------------------------------------+
| TIME_TO_SEC(TIMEDIFF(walkEndTime,walkStartTime)) |
+--------------------------------------------------+
|                                              890 |
|                                              950 |
|                                              540 |
|                                              453 |
+--------------------------------------------------+
4 rows in set (0.00 sec)

MariaDB [tmp]> EXPLAIN select TIME_TO_SEC(TIMEDIFF(walkEndTime,walkStartTime))
    -> from users
    -> where categoryType='1'
    -> and TIME_TO_SEC(TIMEDIFF(walkEndTime,walkStartTime)) < 1000;
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id   | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
|    1 | SIMPLE      | users | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using where |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

MariaDB [tmp]>

使用新的 VIRTUAL 字段 (diffp) 运行我的优化查询:

MariaDB [tmp]> SELECT diffp
    -> FROM users
    -> WHERE diffp < 1000;
+-------+
| diffp |
+-------+
|   453 |
|   540 |
|   890 |
|   950 |
+-------+
4 rows in set (0.00 sec)

MariaDB [tmp]> EXPLAIN SELECT diffp
    -> FROM users
    -> WHERE diffp < 1000;
+------+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|    1 | SIMPLE      | users | range | diffs         | diffs | 5       | NULL |    3 | Using where; Using index |
+------+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
1 row in set (0.00 sec)

MariaDB [tmp]>

所以你可以看到MySQL只读取3行并使用索引。 当您在两个字段(diffp 和 CategoryType)上使用复合索引时,也有可能可以提高速度,并且索引中两个字段的顺序也可以改变速度。

关于mysql - 优化MYSQL查询TIMEDIFF中Select和where子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32804585/

相关文章:

Python mysql 字符串替换不起作用

mysql - 如何解决这个极其慢的 MYSQL 查询

mysql - 推荐 "to optimize the response time of an SQL query"

mysql - 如何优化多连接的慢查询

mysql - MySQL 表中的常量列值

mysql - vb.net中mysql语法错误

mysql - SQL 查询选择和更新

c++ - 类模板别名在生成的符号中不应该是可见的,是吗?

ruby-on-rails - 测试与 alias_attribute 的关联

c# - 错误 "check the manual that corresponds to your MySQL server version"