MySQL按时间顺序查询最近800个条目的速度

vas*_*voc 5 mysql performance query-performance

我有一个运行在 Ubuntu 机器上的 MySQL 数据库,它每分钟 (24x7) ping 250 个客户端。我的列名是:

ip_address varchar(16),
status varchar(7),
timestamp datetime 
Run Code Online (Sandbox Code Playgroud)

运行它几个星期,它已经增长(10,581,421+ 行)。我运行查询以返回特定 IP 地址上的最新 800 个结果:

SELECT *
FROM (
    SELECT Device_ip, Status, timestamp
    FROM ping_results
    where Device_ip = '192.168.1.1'
    order by timestamp desc
    LIMIT 800
) SUB ORDER BY timestamp asc;
Run Code Online (Sandbox Code Playgroud)

返回结果需要 10+ 秒。有什么我可以做的不同的事情来加快速度吗?

Neg*_*sro 8

您可以像这样跳出该子查询:

SELECT Device_ip, Status, timestamp
    FROM ping_results
    WHERE Device_ip = '192.168.1.1'
    AND timestamp > DATE_SUB(NOW(), INTERVAL 800 MINUTE )
    ORDER BY timestamp ASC
Run Code Online (Sandbox Code Playgroud)

这应该稍微简化查询计划,并且您只执行一个 ORDER BY 而不是两个。

正如其他人也提到的,索引是提高性能的一个好主意,并且可能不仅仅是操作查询。

  • 漂亮又狡猾;) (2认同)

Rol*_*DBA 2

查看查询,我发现您需要按升序检索 800 个最近的 ping。

您应该能够使用以下索引改进查询

ALTER TABLE ping_results ADD INDEX DEV_TIME_IP_NDX (`Device_ip`,`timestamp`,`ip_address`);
Run Code Online (Sandbox Code Playgroud)

这将通过以下方式帮助您的查询

  • 很快就ORDER BY减少到特定的向后索引扫描device_ip
  • 由于所有三列都在索引中,因此该表不用于检索任何数据

试一试 !!!

更新 2014-11-03 16:05 美国东部时间

如果 ping_results 表有一id列,您可能可以使用 JOIN 重做查询

SELECT B.Device_ip, B.Status, B.timestamp FROM
(
    SELECT id FROM
    (
        SELECT id,timestamp FROM ping_results
        where Device_ip = '192.168.1.1'
        order by timestamp desc LIMIT 800
    ) SUB ORDER BY timestamp
) A LEFT JOIN ping_results B USING (id);
Run Code Online (Sandbox Code Playgroud)

创建我建议的索引后,您应该针对此查询和原始查询运行解释计划。然后,选择最佳解释计划或运行最快的查询。有可能,您的第一个查询应该足够了,因为它在查询优化器中需要处理的“噪音更少”。

顺便说一句,我使用 LEFT JOIN 因为 id 值将保持在子查询中的顺序。执行 INNER JOIN 会无意中对键进行重新排序。