我正试图想出一种收集数据集的方法,而不必循环700,000次mysql查询。
我有两张桌子
users
id autoincrement,
time timestamp,
username varchar(200),
email varchar(100),
ip varchar(20)
和uniq_ip
与
ip unique varchar(20),
most_recent datetime,
count (int)
users
有2500万行,记录用户在网站上工作时的活动。 uniq_ip
列出了所有IP号码以及在用户中列出的次数(触发更新时)。
目前,在进行白日梦编码时,我会从uniq_ip
获取所有IP的列表并循环它们以获取每个IP的最新2000条记录。由于uniq_ip
有700,000行,这个循环非常讨厌,使用
select * from users where ip = '$outerloopip' order by `time` desc limit 2000;
我正在尝试获取一个查询,该查询将获取每个IP的最新2000个列表。如果1.2.3.4被列出10,000次,我只想要最近的2000,基于时间字段。
如何在一个查询中执行此操作?
答案 0 :(得分:1)
对于之前的回答感到抱歉,重新阅读并应用了更新的查询。我错过了,并认为你只想要最近的2000个IP地址。无论如何,这个地址会执行所有IP地址,并将每个IP的总记录限制为2,000个条目,最近一个位于顶部。我会确保你有一个索引
(IP,TIME DESC)
然后,尝试此查询。我错过了澄清的关键事项。 HAVING子句在任何group-by或order-by子句之后应用。因此,数据按正确的IP地址和日期/时间DESCENDING顺序预先返回,然后应用@sql变量。一旦记录被限定并且READY被添加到最终结果集,就应用HAVING子句。在那一刻,它查看了序列计数器并说...如果它大于2000,则抛出它并继续下一条记录。
根据我的原始查询,它正在保存所有内容,然后循环第二次并踢出超过2000的那些,这可能就是为什么它会让你的磁盘空间消失。
select
U.*,
@LastSeq := IF( @LastIP = U.IP, @LastSeq +1, 1 ) as IPSequence,
@LastIP := U.IP as carryForNextRecord
from
( select @LastIP := '', @LastSeq := 0 ) sqlvars,
Users U
order by
U.IP,
U.time DESC
having
IPSequence <= 2000
答案 1 :(得分:0)
SELECT ip as IP ,
(SELECT GROUP_CONCAT(time) FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as Time,
(SELECT GROUP_CONCAT(username) FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as UserName,
(SELECT GROUP_CONCAT(email) FROM users WHERE ip = IP ORDER BY time DESC LIMIT 2000) as Email
FROM uniq_id