【发布时间】:2017-05-20 12:14:08
【问题描述】:
我有一个名为lead_history 的表,当我从中计算平均值时,查询需要一分半钟。该查询正在解析大约 15k 行。我已经根据以下查询添加了索引,但似乎仍然需要很长时间。任何帮助将不胜感激。
SELECT AVG(TIMEDIFF(tq.ts, tv.ts)) / 60 avg_time_to_quote
FROM lead_history tv
JOIN lead_history tq
ON tv.agency_id = tq.agency_id
WHERE tv.new_status = 'Verified'
AND tq.new_status = 'Quoted'
AND tv.agency_id = '$agency_id'
AND tv.ts > DATE_SUB(NOW(), INTERVAL 30 DAY)
AND tq.ts > DATE_SUB(NOW(), INTERVAL 30 DAY)
GROUP
BY tv.agency_id
, tq.agency_id
表结构
show create table lead_history;
+--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| lead_history | CREATE TABLE `lead_history` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`agency_id` varchar(255) NOT NULL,
`old_status` varchar(64) DEFAULT NULL,
`new_status` varchar(64) DEFAULT NULL,
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`contact_id` varchar(255) NOT NULL DEFAULT '',
`alter_type` varchar(255) NOT NULL DEFAULT '',
`last_mod_by` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `avg_index` (`old_status`,`new_status`,`agency_id`,`ts`)
) ENGINE=InnoDB AUTO_INCREMENT=14041 DEFAULT CHARSET=latin1 |
+--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
索引
mysql> show indexes from lead_history;
+--------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| lead_history | 0 | PRIMARY | 1 | id | A | 13922 | NULL | NULL | | BTREE | | |
| lead_history | 1 | avg_index | 1 | old_status | A | 18 | NULL | NULL | YES | BTREE | | |
| lead_history | 1 | avg_index | 2 | new_status | A | 46 | NULL | NULL | YES | BTREE | | |
| lead_history | 1 | avg_index | 3 | agency_id | A | 48 | NULL | NULL | | BTREE | | |
| lead_history | 1 | avg_index | 4 | ts | A | 1330 | NULL | NULL | | BTREE | | |
+--------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+`
解释`
mysql> explain select avg(UNIX_TIMESTAMP(tq.ts) - UNIX_TIMESTAMP(tv.ts)) / 60 as avg_time_to_quote from lead_history tv join lead_history tq on tv.agency_id = tq.agency_id WHERE tv.old_status not like 'Verified' and tq.new_status = 'Verified' and tv.agency_id and tv.agency_id = 'XXXXXXXXXXXX35';
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+-------+----------+-----------------------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+-------+----------+-----------------------------------------------------------------+
| 1 | SIMPLE | tq | NULL | index | NULL | avg_index | 395 | NULL | 13922 | 1.00 | Using where; Using index |
| 1 | SIMPLE | tv | NULL | index | NULL | avg_index | 395 | NULL | 13922 | 8.00 | Using where; Using index; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+-------+----------+-----------------------------------------------------------------+
2 rows in set, 1 warning (0.02 sec)
mysql>
`
【问题讨论】:
-
查看这个问题的答案:stackoverflow.com/questions/3528219/… 它说减去
UNIX_TIMESTAMP(a)-UNIX_TIMESTAMP(b)可以比在 TIMESTAMP 字段上使用 TIMEDIFF 更快。 -
哇!我不敢相信这有多大的不同。将查询缩短一分钟。不过,30 秒似乎仍然很长。还有其他想法吗?
-
您有带间隔的 DATE_SUB() 函数。从 UNIX_TIMESTAMP(TIMESTAMP) 中减去一个整数 = 30 天 * 24 小时 * 3600 秒怎么样?
-
顺便说一句,我觉得 SHOW CREATE TABLE 比 DESCRIBE 更容易阅读
-
@Strawberry 那是显示创建表。 注意 - 我明白你的意思,那绝对不是 show create table,抱歉混淆了,改了。
标签: php mysql indexing average