我有一个包含100k行的MySQL表,它捕获了一些创建的服务器日志:
CREATE TABLE `logs` (
`id` INT NOT NULL AUTO_INCREMENT,
`ip` VARCHAR(16) NULL,
`date` DATETIME NULL,
`session_time` SMALLINT UNSIGNED NULL,
PRIMARY KEY (`id`));
我正在尝试将会话时间计算为同一ip的连续行之间的时间差。我能够通过以下选择查询实现这一目标,该查询只需不到一秒钟:
SELECT * FROM logs AS a
LEFT JOIN (
SELECT id,
from_unixtime(@diff) AS starttime,
date AS endtime,
IF(@diff = 0, 0, (unix_timestamp(date) - @diff)/60) AS session_time1,
@diff := unix_timestamp(date)
FROM logs,
(SELECT @diff := 0) AS x
ORDER BY ip, logs.date
) AS b ON
a.id = b.id
但是,当我尝试在update-join中使用先前的查询来更新时间会话时,以下更新查询需要超过600秒:
UPDATE logs AS a
LEFT JOIN (
SELECT id,
from_unixtime(@diff) AS starttime,
date AS endtime,
IF(@diff = 0, 0, (unix_timestamp(date) - @diff)/60) AS session_time1,
@diff := unix_timestamp(date)
FROM logs,
(SELECT @diff := 0) AS x
ORDER BY ip, logs.date
) AS b ON
a.id = b.id
SET session_time = session_time1;
我错过了什么?
谢谢!
更新:以下是EXPLAIN
的{{1}}:
select
答案 0 :(得分:0)
从所有行中的session_time
NULL
开始。以两种方式更改查询:
WHERE session_time IS NULL
添加到UPDATE(最后)session_time
设置为NULL
,否则请将其正确设置。第一个晚上,它会像现在一样慢,但在那之后,它会快得多,因为它只能处理几个“新”行。
修改强>
JOIN
需要(通常)一个ON
子句。如何将logs
和a
与PRIMARY KEY
的{{1}}联系起来。 logs
表示需要运行EXPLAIN
和logs
的109K * 108K组合;它应该只有109K。
此外,除非有必要,否则请删除a
。